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"
71 #include "nsIEventListenerManager.h"
73 #include "nsStyleCoord.h"
74 #include "nsMimeTypeArray.h"
75 #include "nsNetUtil.h"
76 #include "nsICachingChannel.h"
77 #include "nsPluginArray.h"
78 #include "nsIPluginHost.h"
79 #include "nsGeolocation.h"
80 #include "nsDesktopNotification.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 #ifndef MOZ_DISABLE_DOMCRYPTO
107 #include "nsIDOMCrypto.h"
109 #include "nsIDOMDocument.h"
110 #include "nsIDOM3Document.h"
111 #include "nsIDOMNSDocument.h"
112 #include "nsIDOMDocumentView.h"
113 #include "nsIDOMElement.h"
114 #include "nsIDOMDocumentEvent.h"
115 #include "nsIDOMEvent.h"
116 #include "nsIDOMHTMLAnchorElement.h"
117 #include "nsIDOMKeyEvent.h"
118 #include "nsIDOMMessageEvent.h"
119 #include "nsIDOMPopupBlockedEvent.h"
120 #include "nsIDOMPopStateEvent.h"
121 #include "nsIDOMOfflineResourceList.h"
122 #include "nsIDOMGeoGeolocation.h"
123 #include "nsIDOMDesktopNotification.h"
124 #include "nsPIDOMStorage.h"
125 #include "nsDOMString.h"
126 #include "nsIEmbeddingSiteWindow2.h"
127 #include "nsThreadUtils.h"
128 #include "nsIEventStateManager.h"
129 #include "nsIHttpProtocolHandler.h"
130 #include "nsIJSContextStack.h"
131 #include "nsIJSRuntimeService.h"
132 #include "nsIMarkupDocumentViewer.h"
133 #include "nsIPrefBranch.h"
134 #include "nsIPresShell.h"
135 #include "nsIPrivateDOMEvent.h"
136 #include "nsIProgrammingLanguage.h"
137 #include "nsIServiceManager.h"
138 #include "nsIScriptGlobalObjectOwner.h"
139 #include "nsIScriptSecurityManager.h"
140 #include "nsIScrollableFrame.h"
142 #include "nsIViewManager.h"
143 #include "nsISelectionController.h"
144 #include "nsISelection.h"
145 #include "nsIPrompt.h"
146 #include "nsIPromptService.h"
147 #include "nsIPromptFactory.h"
148 #include "nsIWritablePropertyBag2.h"
149 #include "nsIWebNavigation.h"
150 #include "nsIWebBrowser.h"
151 #include "nsIWebBrowserChrome.h"
152 #include "nsIWebBrowserFind.h" // For window.find()
153 #include "nsIWebContentHandlerRegistrar.h"
154 #include "nsIWindowMediator.h" // For window.find()
155 #include "nsComputedDOMStyle.h"
156 #include "nsIEntropyCollector.h"
157 #include "nsDOMCID.h"
158 #include "nsDOMError.h"
159 #include "nsDOMWindowUtils.h"
160 #include "nsIWindowWatcher.h"
161 #include "nsPIWindowWatcher.h"
162 #include "nsIContentViewer.h"
163 #include "nsDOMClassInfo.h"
164 #include "nsIJSNativeInitializer.h"
165 #include "nsIScriptError.h"
166 #include "nsIScriptEventManager.h" // For GetInterface()
167 #include "nsIConsoleService.h"
168 #include "nsIControllers.h"
169 #include "nsIControllerContext.h"
170 #include "nsGlobalWindowCommands.h"
171 #include "nsAutoPtr.h"
172 #include "nsContentUtils.h"
173 #include "nsCSSProps.h"
174 #include "nsFileDataProtocolHandler.h"
175 #include "nsIDOMFile.h"
176 #include "nsIURIFixup.h"
177 #include "mozilla/FunctionTimer.h"
178 #include "nsCDefaultURIFixup.h"
179 #include "nsEventDispatcher.h"
180 #include "nsIObserverService.h"
181 #include "nsIXULAppInfo.h"
182 #include "nsNetUtil.h"
183 #include "nsFocusManager.h"
185 #include "nsIXULWindow.h"
186 #include "nsEventStateManager.h"
188 #include "nsXULPopupManager.h"
189 #include "nsIDOMXULControlElement.h"
190 #include "nsIFrame.h"
193 #include "xpcprivate.h"
196 #include "nsIPrintSettings.h"
197 #include "nsIPrintSettingsService.h"
198 #include "nsIWebBrowserPrint.h"
201 #include "nsWindowRoot.h"
202 #include "nsNetCID.h"
203 #include "nsIArray.h"
204 #include "nsIScriptRuntime.h"
206 // XXX An unfortunate dependency exists here (two XUL files).
207 #include "nsIDOMXULDocument.h"
208 #include "nsIDOMXULCommandDispatcher.h"
210 #include "nsBindingManager.h"
211 #include "nsIXBLService.h"
213 // used for popup blocking, needs to be converted to something
214 // belonging to the back-end like nsIContentPolicy
215 #include "nsIPopupWindowManager.h"
217 #include "nsIDragService.h"
218 #include "mozilla/dom/Element.h"
219 #include "nsFrameLoader.h"
220 #include "nsISupportsPrimitives.h"
221 #include "nsXPCOMCID.h"
223 #include "mozilla/FunctionTimer.h"
224 #include "mozIThirdPartyUtil.h"
227 // so we can get logging even in release builds
228 #define FORCE_PR_LOG 1
232 #include "mozilla/dom/indexedDB/IDBFactory.h"
233 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
235 #include "nsRefreshDriver.h"
238 static PRLogModuleInfo
* gDOMLeakPRLog
;
241 static const char kStorageEnabled
[] = "dom.storage.enabled";
243 using namespace mozilla::dom
;
244 using mozilla::TimeStamp
;
245 using mozilla::TimeDuration
;
247 nsIDOMStorageList
*nsGlobalWindow::sGlobalStorageList
= nsnull
;
248 nsGlobalWindow::WindowByIdTable
*nsGlobalWindow::sOuterWindowsById
= nsnull
;
250 static nsIEntropyCollector
*gEntropyCollector
= nsnull
;
251 static PRInt32 gRefCnt
= 0;
252 static PRInt32 gOpenPopupSpamCount
= 0;
253 static PopupControlState gPopupControlState
= openAbused
;
254 static PRInt32 gRunningTimeoutDepth
= 0;
255 static PRPackedBool gMouseDown
= PR_FALSE
;
256 static PRPackedBool gDragServiceDisabled
= PR_FALSE
;
257 static FILE *gDumpFile
= nsnull
;
258 static PRUint64 gNextWindowID
= 0;
259 static PRUint32 gSerialCounter
= 0;
262 PRInt32 gTimeoutCnt
= 0;
265 #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
266 static PRBool gDOMWindowDumpEnabled
= PR_FALSE
;
269 #if defined(DEBUG_bryner) || defined(DEBUG_chb)
270 #define DEBUG_PAGE_CACHE
273 // The default shortest interval/timeout we permit
274 #define DEFAULT_MIN_TIMEOUT_VALUE 10 // 10ms
275 static PRInt32 gMinTimeoutValue
;
276 static inline PRInt32
DOMMinTimeoutValue() {
277 return NS_MAX(gMinTimeoutValue
, 0);
280 // The number of nested timeouts before we start clamping. HTML5 says 1, WebKit
282 #define DOM_CLAMP_TIMEOUT_NESTING_LEVEL 5
284 // The longest interval (as PRIntervalTime) we permit, or that our
285 // timer code can handle, really. See DELAY_INTERVAL_LIMIT in
286 // nsTimerImpl.h for details.
287 #define DOM_MAX_TIMEOUT_VALUE PR_BIT(8 * sizeof(PRIntervalTime) - 1)
289 #define FORWARD_TO_OUTER(method, args, err_rval) \
291 if (IsInnerWindow()) { \
292 nsGlobalWindow *outer = GetOuterWindowInternal(); \
294 NS_WARNING("No outer window available!"); \
297 return outer->method args; \
301 #define FORWARD_TO_OUTER_VOID(method, args) \
303 if (IsInnerWindow()) { \
304 nsGlobalWindow *outer = GetOuterWindowInternal(); \
306 NS_WARNING("No outer window available!"); \
309 outer->method args; \
314 #define FORWARD_TO_OUTER_CHROME(method, args, err_rval) \
316 if (IsInnerWindow()) { \
317 nsGlobalWindow *outer = GetOuterWindowInternal(); \
319 NS_WARNING("No outer window available!"); \
322 return ((nsGlobalChromeWindow *)outer)->method args; \
326 #define FORWARD_TO_INNER_CHROME(method, args, err_rval) \
328 if (IsOuterWindow()) { \
329 if (!mInnerWindow) { \
330 NS_WARNING("No inner window available!"); \
333 return ((nsGlobalChromeWindow *)mInnerWindow)->method args; \
337 #define FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(method, args, err_rval) \
339 if (IsInnerWindow()) { \
340 nsGlobalWindow *outer = GetOuterWindowInternal(); \
342 NS_WARNING("No outer window available!"); \
345 return ((nsGlobalModalWindow *)outer)->method args; \
349 #define FORWARD_TO_INNER(method, args, err_rval) \
351 if (IsOuterWindow()) { \
352 if (!mInnerWindow) { \
353 NS_WARNING("No inner window available!"); \
356 return GetCurrentInnerWindowInternal()->method args; \
360 #define FORWARD_TO_INNER_MODAL_CONTENT_WINDOW(method, args, err_rval) \
362 if (IsOuterWindow()) { \
363 if (!mInnerWindow) { \
364 NS_WARNING("No inner window available!"); \
367 return ((nsGlobalModalWindow*)GetCurrentInnerWindowInternal())->method args; \
371 #define FORWARD_TO_INNER_VOID(method, args) \
373 if (IsOuterWindow()) { \
374 if (!mInnerWindow) { \
375 NS_WARNING("No inner window available!"); \
378 GetCurrentInnerWindowInternal()->method args; \
383 // Same as FORWARD_TO_INNER, but this will create a fresh inner if an
384 // inner doesn't already exists.
385 #define FORWARD_TO_INNER_CREATE(method, args, err_rval) \
387 if (IsOuterWindow()) { \
388 if (!mInnerWindow) { \
392 nsCOMPtr<nsIDOMDocument> doc; \
393 nsresult fwdic_nr = GetDocument(getter_AddRefs(doc)); \
394 NS_ENSURE_SUCCESS(fwdic_nr, err_rval); \
395 if (!mInnerWindow) { \
399 return GetCurrentInnerWindowInternal()->method args; \
404 static NS_DEFINE_CID(kXULControllersCID
, NS_XULCONTROLLERS_CID
);
406 static const char sJSStackContractID
[] = "@mozilla.org/js/xpc/ContextStack;1";
407 #ifndef MOZ_DISABLE_DOMCRYPTO
408 static const char kCryptoContractID
[] = NS_CRYPTO_CONTRACTID
;
409 static const char kPkcs11ContractID
[] = NS_PKCS11_CONTRACTID
;
411 static const char sPopStatePrefStr
[] = "browser.history.allowPopState";
414 IsAboutBlank(nsIURI
* aURI
)
416 NS_PRECONDITION(aURI
, "Must have URI");
418 // GetSpec can be expensive for some URIs, so check the scheme first.
419 PRBool isAbout
= PR_FALSE
;
420 if (NS_FAILED(aURI
->SchemeIs("about", &isAbout
)) || !isAbout
) {
426 return str
.EqualsLiteral("about:blank");
429 class nsDummyJavaPluginOwner
: public nsIPluginInstanceOwner
432 nsDummyJavaPluginOwner(nsIDocument
*aDocument
)
433 : mDocument(aDocument
)
439 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
440 NS_DECL_NSIPLUGININSTANCEOWNER
442 NS_IMETHOD
GetURL(const char *aURL
, const char *aTarget
,
443 nsIInputStream
*aPostStream
,
444 void *aHeadersData
, PRUint32 aHeadersDataLen
);
445 NS_IMETHOD
ShowStatus(const PRUnichar
*aStatusMsg
);
446 NPError
ShowNativeContextMenu(NPMenu
* menu
, void* event
);
447 NPBool
ConvertPoint(double sourceX
, double sourceY
, NPCoordinateSpace sourceSpace
,
448 double *destX
, double *destY
, NPCoordinateSpace destSpace
);
449 void SendIdleEvent();
451 NS_DECL_CYCLE_COLLECTION_CLASS(nsDummyJavaPluginOwner
)
454 nsCOMPtr
<nsIPluginInstance
> mInstance
;
455 nsCOMPtr
<nsIDocument
> mDocument
;
458 NS_IMPL_CYCLE_COLLECTION_2(nsDummyJavaPluginOwner
, mDocument
, mInstance
)
460 // QueryInterface implementation for nsDummyJavaPluginOwner
461 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDummyJavaPluginOwner
)
462 NS_INTERFACE_MAP_ENTRY(nsISupports
)
463 NS_INTERFACE_MAP_ENTRY(nsIPluginInstanceOwner
)
466 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDummyJavaPluginOwner
)
467 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDummyJavaPluginOwner
)
471 nsDummyJavaPluginOwner::Destroy()
473 // If we have a plugin instance, stop it and destroy it now.
476 mInstance
->InvalidateOwner();
484 nsDummyJavaPluginOwner::SetInstance(nsIPluginInstance
*aInstance
)
486 // If we're going to null out mInstance after use, be sure to call
487 // mInstance->InvalidateOwner() here, since it now won't be called
488 // from nsDummyJavaPluginOwner::Destroy().
489 if (mInstance
&& !aInstance
)
490 mInstance
->InvalidateOwner();
492 mInstance
= aInstance
;
498 nsDummyJavaPluginOwner::GetInstance(nsIPluginInstance
*&aInstance
)
500 NS_IF_ADDREF(aInstance
= mInstance
);
506 nsDummyJavaPluginOwner::GetWindow(NPWindow
*&aWindow
)
514 nsDummyJavaPluginOwner::GetMode(PRInt32
*aMode
)
516 // This is wrong, but there's no better alternative.
519 return NS_ERROR_NOT_IMPLEMENTED
;
523 nsDummyJavaPluginOwner::CreateWidget(void)
525 return NS_ERROR_NOT_IMPLEMENTED
;
529 nsDummyJavaPluginOwner::GetURL(const char *aURL
, const char *aTarget
,
530 nsIInputStream
*aPostStream
,
531 void *aHeadersData
, PRUint32 aHeadersDataLen
)
533 return NS_ERROR_NOT_IMPLEMENTED
;
537 nsDummyJavaPluginOwner::ShowStatus(const char *aStatusMsg
)
539 return NS_ERROR_NOT_IMPLEMENTED
;
543 nsDummyJavaPluginOwner::ShowStatus(const PRUnichar
*aStatusMsg
)
545 return NS_ERROR_NOT_IMPLEMENTED
;
549 nsDummyJavaPluginOwner::ShowNativeContextMenu(NPMenu
* menu
, void* event
)
551 return NPERR_GENERIC_ERROR
;
555 nsDummyJavaPluginOwner::ConvertPoint(double sourceX
, double sourceY
, NPCoordinateSpace sourceSpace
,
556 double *destX
, double *destY
, NPCoordinateSpace destSpace
)
562 nsDummyJavaPluginOwner::GetDocument(nsIDocument
**aDocument
)
564 NS_IF_ADDREF(*aDocument
= mDocument
);
570 nsDummyJavaPluginOwner::InvalidateRect(NPRect
*invalidRect
)
572 return NS_ERROR_NOT_IMPLEMENTED
;
576 nsDummyJavaPluginOwner::InvalidateRegion(NPRegion invalidRegion
)
578 return NS_ERROR_NOT_IMPLEMENTED
;
582 nsDummyJavaPluginOwner::ForceRedraw()
584 return NS_ERROR_NOT_IMPLEMENTED
;
588 nsDummyJavaPluginOwner::GetNetscapeWindow(void *value
)
590 return NS_ERROR_NOT_IMPLEMENTED
;
594 nsDummyJavaPluginOwner::SetEventModel(PRInt32 eventModel
)
596 return NS_ERROR_NOT_IMPLEMENTED
;
600 nsDummyJavaPluginOwner::SendIdleEvent()
605 * An object implementing the window.URL property.
607 class nsDOMMozURLProperty
: public nsIDOMMozURLProperty
610 nsDOMMozURLProperty(nsGlobalWindow
* aWindow
)
616 NS_DECL_NSIDOMMOZURLPROPERTY
618 void ClearWindowReference() {
622 nsGlobalWindow
* mWindow
;
625 DOMCI_DATA(MozURLProperty
, nsDOMMozURLProperty
)
626 NS_IMPL_ADDREF(nsDOMMozURLProperty
)
627 NS_IMPL_RELEASE(nsDOMMozURLProperty
)
628 NS_INTERFACE_MAP_BEGIN(nsDOMMozURLProperty
)
629 NS_INTERFACE_MAP_ENTRY(nsIDOMMozURLProperty
)
630 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMMozURLProperty
)
631 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozURLProperty
)
635 nsDOMMozURLProperty::CreateObjectURL(nsIDOMBlob
* aBlob
, nsAString
& aURL
)
637 NS_PRECONDITION(!mWindow
|| mWindow
->IsInnerWindow(),
638 "Should be inner window");
640 NS_ENSURE_STATE(mWindow
&& mWindow
->mDoc
);
641 NS_ENSURE_ARG_POINTER(aBlob
);
643 nsIDocument
* doc
= mWindow
->mDoc
;
645 nsresult rv
= aBlob
->GetInternalUrl(doc
->NodePrincipal(), aURL
);
646 NS_ENSURE_SUCCESS(rv
, rv
);
648 doc
->RegisterFileDataUri(NS_LossyConvertUTF16toASCII(aURL
));
654 nsDOMMozURLProperty::RevokeObjectURL(const nsAString
& aURL
)
656 NS_PRECONDITION(!mWindow
|| mWindow
->IsInnerWindow(),
657 "Should be inner window");
659 NS_ENSURE_STATE(mWindow
);
661 NS_LossyConvertUTF16toASCII
asciiurl(aURL
);
663 nsIPrincipal
* winPrincipal
= mWindow
->GetPrincipal();
668 nsIPrincipal
* principal
=
669 nsFileDataProtocolHandler::GetFileDataEntryPrincipal(asciiurl
);
671 if (principal
&& winPrincipal
&&
672 NS_SUCCEEDED(winPrincipal
->Subsumes(principal
, &subsumes
)) &&
675 mWindow
->mDoc
->UnregisterFileDataUri(asciiurl
);
677 nsFileDataProtocolHandler::RemoveFileDataEntry(asciiurl
);
684 * An indirect observer object that means we don't have to implement nsIObserver
685 * on nsGlobalWindow, where any script could see it.
687 class nsGlobalWindowObserver
: public nsIObserver
{
689 nsGlobalWindowObserver(nsGlobalWindow
* aWindow
) : mWindow(aWindow
) {}
691 NS_IMETHOD
Observe(nsISupports
* aSubject
, const char* aTopic
, const PRUnichar
* aData
)
695 return mWindow
->Observe(aSubject
, aTopic
, aData
);
697 void Forget() { mWindow
= nsnull
; }
699 nsGlobalWindow
* mWindow
;
702 NS_IMPL_ISUPPORTS1(nsGlobalWindowObserver
, nsIObserver
)
704 nsTimeout::nsTimeout()
708 extern int gTimeoutCnt
;
714 memset(this, 0, sizeof(*this));
716 MOZ_COUNT_CTOR(nsTimeout
);
719 nsTimeout::~nsTimeout()
723 extern int gTimeoutCnt
;
729 MOZ_COUNT_DTOR(nsTimeout
);
732 NS_IMPL_CYCLE_COLLECTION_CLASS(nsTimeout
)
733 NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsTimeout
)
734 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsTimeout
)
735 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mWindow
,
736 nsIScriptGlobalObject
)
737 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrincipal
)
738 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptHandler
)
739 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
740 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTimeout
, AddRef
)
741 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsTimeout
, Release
)
743 nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow
*aOuterWindow
)
744 : mFrameElement(nsnull
), mDocShell(nsnull
), mModalStateDepth(0),
745 mRunningTimeout(nsnull
), mMutationBits(0), mIsDocumentLoaded(PR_FALSE
),
746 mIsHandlingResizeEvent(PR_FALSE
), mIsInnerWindow(aOuterWindow
!= nsnull
),
747 mMayHavePaintEventListener(PR_FALSE
), mMayHaveTouchEventListener(PR_FALSE
),
748 mMayHaveAudioAvailableEventListener(PR_FALSE
), mIsModalContentWindow(PR_FALSE
),
749 mIsActive(PR_FALSE
), mInnerWindow(nsnull
), mOuterWindow(aOuterWindow
),
750 // Make sure no actual window ends up with mWindowID == 0
751 mWindowID(++gNextWindowID
), mHasNotifiedGlobalCreated(PR_FALSE
)
754 nsPIDOMWindow::~nsPIDOMWindow() {}
756 //*****************************************************************************
757 // nsOuterWindowProxy: Outer Window Proxy
758 //*****************************************************************************
761 nsOuterWindowProxy::obj_toString(JSContext
*cx
, JSObject
*proxy
)
763 JS_ASSERT(proxy
->isProxy());
765 return JS_NewStringCopyZ(cx
, "[object Window]");
769 nsOuterWindowProxy::singleton
;
772 NS_NewOuterWindowProxy(JSContext
*cx
, JSObject
*parent
)
774 JSAutoEnterCompartment ac
;
775 if (!ac
.enter(cx
, parent
)) {
779 JSObject
*obj
= JSWrapper::New(cx
, parent
, parent
->getProto(), parent
,
780 &nsOuterWindowProxy::singleton
);
781 NS_ASSERTION(obj
->getClass()->ext
.innerObject
, "bad class");
785 //*****************************************************************************
786 //*** nsGlobalWindow: Object Management
787 //*****************************************************************************
789 nsGlobalWindow::nsGlobalWindow(nsGlobalWindow
*aOuterWindow
)
790 : nsPIDOMWindow(aOuterWindow
),
792 mDidInitJavaProperties(PR_FALSE
),
793 mFullScreen(PR_FALSE
),
796 mHavePendingClose(PR_FALSE
),
797 mHadOriginalOpener(PR_FALSE
),
798 mIsPopupSpam(PR_FALSE
),
799 mBlockScriptedClosingFlag(PR_FALSE
),
800 mFireOfflineStatusChangeEventOnThaw(PR_FALSE
),
801 mCreatingInnerWindow(PR_FALSE
),
803 mCleanMessageManager(PR_FALSE
),
804 mNeedsFocus(PR_TRUE
),
806 #if defined(XP_MAC) || defined(XP_MACOSX)
807 mShowAccelerators(PR_FALSE
),
808 mShowFocusRings(PR_FALSE
),
810 mShowAccelerators(PR_TRUE
),
811 mShowFocusRings(PR_TRUE
),
813 mShowFocusRingForContent(PR_FALSE
),
814 mFocusByKeyOccurred(PR_FALSE
),
815 mHasAcceleration(PR_FALSE
),
816 mNotifiedIDDestroyed(PR_FALSE
),
817 mTimeoutInsertionPoint(nsnull
),
818 mTimeoutPublicIdCounter(1),
819 mTimeoutFiringDepth(0),
821 mPendingStorageEventsObsolete(nsnull
),
822 mTimeoutsSuspendDepth(0),
826 mSetOpenerWindowCalled(PR_FALSE
),
828 mCleanedUp(PR_FALSE
),
829 mCallCleanUpAfterModalDialogCloses(PR_FALSE
),
830 mDialogAbuseCount(0),
831 mDialogDisabled(PR_FALSE
)
833 nsLayoutStatics::AddRef();
835 // Initialize the PRCList (this).
838 // Initialize timeout storage
839 PR_INIT_CLIST(&mTimeouts
);
842 // |this| is an inner window, add this inner window to the outer
843 // window list of inners.
844 PR_INSERT_AFTER(this, aOuterWindow
);
846 mObserver
= new nsGlobalWindowObserver(this);
848 NS_ADDREF(mObserver
);
849 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
851 // Watch for online/offline status changes so we can fire events. Use
852 // a strong reference.
853 os
->AddObserver(mObserver
, NS_IOSERVICE_OFFLINE_STATUS_TOPIC
,
856 // Watch for dom-storage-changed so we can fire storage
857 // events. Use a strong reference.
858 os
->AddObserver(mObserver
, "dom-storage2-changed", PR_FALSE
);
859 os
->AddObserver(mObserver
, "dom-storage-changed", PR_FALSE
);
863 // |this| is an outer window. Outer windows start out frozen and
864 // remain frozen until they get an inner window, so freeze this
865 // outer window here.
871 if (!sOuterWindowsById
) {
872 sOuterWindowsById
= new WindowByIdTable();
873 if (!sOuterWindowsById
->Init()) {
874 delete sOuterWindowsById
;
875 sOuterWindowsById
= nsnull
;
879 if (sOuterWindowsById
) {
880 sOuterWindowsById
->Put(mWindowID
, this);
884 // We could have failed the first time through trying
885 // to create the entropy collector, so we should
886 // try to get one until we succeed.
891 #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
892 nsContentUtils::AddBoolPrefVarCache("browser.dom.window.dump.enabled",
893 &gDOMWindowDumpEnabled
);
895 nsContentUtils::AddIntPrefVarCache("dom.min_timeout_value",
897 DEFAULT_MIN_TIMEOUT_VALUE
);
900 if (gDumpFile
== nsnull
) {
901 const nsAdoptingCString
& fname
=
902 nsContentUtils::GetCharPref("browser.dom.window.dump.file");
903 if (!fname
.IsEmpty()) {
904 // if this fails to open, Dump() knows to just go to stdout
906 gDumpFile
= fopen(fname
, "wb+");
912 if (!gEntropyCollector
) {
913 CallGetService(NS_ENTROPYCOLLECTOR_CONTRACTID
, &gEntropyCollector
);
916 mSerial
= ++gSerialCounter
;
919 printf("++DOMWINDOW == %d (%p) [serial = %d] [outer = %p]\n", gRefCnt
,
920 static_cast<void*>(static_cast<nsIScriptGlobalObject
*>(this)),
921 gSerialCounter
, static_cast<void*>(aOuterWindow
));
926 gDOMLeakPRLog
= PR_NewLogModule("DOMLeak");
929 PR_LOG(gDOMLeakPRLog
, PR_LOG_DEBUG
,
930 ("DOMWINDOW %p created outer=%p", this, aOuterWindow
));
934 nsGlobalWindow::~nsGlobalWindow()
936 if (sOuterWindowsById
) {
937 sOuterWindowsById
->Remove(mWindowID
);
940 NS_IF_RELEASE(gEntropyCollector
);
941 delete sOuterWindowsById
;
942 sOuterWindowsById
= nsnull
;
946 if (mLastOpenedURI
) {
947 mLastOpenedURI
->GetSpec(url
);
950 printf("--DOMWINDOW == %d (%p) [serial = %d] [outer = %p] [url = %s]\n",
951 gRefCnt
, static_cast<void*>(static_cast<nsIScriptGlobalObject
*>(this)),
952 mSerial
, static_cast<void*>(mOuterWindow
.get()), url
.get());
957 PR_LOG(gDOMLeakPRLog
, PR_LOG_DEBUG
,
958 ("DOMWINDOW %p destroyed", this));
961 if (IsOuterWindow()) {
962 // An outer window is destroyed with inner windows still possibly
963 // alive, iterate through the inner windows and null out their
964 // back pointer to this outer, and pull them out of the list of
968 while ((w
= (nsGlobalWindow
*)PR_LIST_HEAD(this)) != this) {
969 PR_REMOVE_AND_INIT_LINK(w
);
972 if (mListenerManager
) {
973 mListenerManager
->Disconnect();
974 mListenerManager
= nsnull
;
977 // An inner window is destroyed, pull it out of the outer window's
978 // list if inner windows.
980 PR_REMOVE_LINK(this);
982 // If our outer window's inner window is this window, null out the
983 // outer window's reference to this window that's being deleted.
984 nsGlobalWindow
*outer
= GetOuterWindowInternal();
985 if (outer
&& outer
->mInnerWindow
== this) {
986 outer
->mInnerWindow
= nsnull
;
990 mDocument
= nsnull
; // Forces Release
993 NS_ASSERTION(!mArguments
, "mArguments wasn't cleaned up properly!");
998 nsCycleCollector_DEBUG_wasFreed(static_cast<nsIScriptGlobalObject
*>(this));
1002 mURLProperty
->ClearWindowReference();
1005 nsLayoutStatics::Release();
1010 nsGlobalWindow::ShutDown()
1012 NS_IF_RELEASE(sGlobalStorageList
);
1014 if (gDumpFile
&& gDumpFile
!= stdout
) {
1022 nsGlobalWindow::CleanupCachedXBLHandlers(nsGlobalWindow
* aWindow
)
1024 if (aWindow
->mCachedXBLPrototypeHandlers
.IsInitialized() &&
1025 aWindow
->mCachedXBLPrototypeHandlers
.Count() > 0) {
1026 aWindow
->mCachedXBLPrototypeHandlers
.Clear();
1028 nsISupports
* supports
;
1029 aWindow
->QueryInterface(NS_GET_IID(nsCycleCollectionISupports
),
1030 reinterpret_cast<void**>(&supports
));
1031 NS_ASSERTION(supports
, "Failed to QI to nsCycleCollectionISupports?!");
1033 nsContentUtils::DropJSObjects(supports
);
1038 nsGlobalWindow::MaybeForgiveSpamCount()
1040 if (IsOuterWindow() &&
1041 IsPopupSpamWindow())
1043 SetPopupSpamWindow(PR_FALSE
);
1044 --gOpenPopupSpamCount
;
1045 NS_ASSERTION(gOpenPopupSpamCount
>= 0,
1046 "Unbalanced decrement of gOpenPopupSpamCount");
1051 nsGlobalWindow::CleanUp(PRBool aIgnoreModalDialog
)
1053 if (IsOuterWindow() && !aIgnoreModalDialog
) {
1054 nsGlobalWindow
* inner
= GetCurrentInnerWindowInternal();
1055 nsCOMPtr
<nsIDOMModalContentWindow
>
1056 dlg(do_QueryInterface(static_cast<nsPIDOMWindow
*>(inner
)));
1058 // The window we're trying to clean up is the outer window of a
1059 // modal dialog. Defer cleanup until the window closes, and let
1060 // ShowModalDialog take care of calling CleanUp.
1061 mCallCleanUpAfterModalDialogCloses
= PR_TRUE
;
1066 // Guarantee idempotence.
1069 mCleanedUp
= PR_TRUE
;
1072 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
1074 os
->RemoveObserver(mObserver
, NS_IOSERVICE_OFFLINE_STATUS_TOPIC
);
1075 os
->RemoveObserver(mObserver
, "dom-storage2-changed");
1076 os
->RemoveObserver(mObserver
, "dom-storage-changed");
1079 // Drop its reference to this dying window, in case for some bogus reason
1080 // the object stays around.
1081 mObserver
->Forget();
1082 NS_RELEASE(mObserver
);
1085 mNavigator
= nsnull
;
1089 mLocationbar
= nsnull
;
1090 mPersonalbar
= nsnull
;
1091 mStatusbar
= nsnull
;
1092 mScrollbars
= nsnull
;
1096 mApplicationCache
= nsnull
;
1097 mIndexedDB
= nsnull
;
1098 mPendingStorageEventsObsolete
= nsnull
;
1103 mOpener
= nsnull
; // Forces Release
1106 nsCycleCollector_DEBUG_shouldBeFreed(mContext
);
1108 mContext
= nsnull
; // Forces Release
1110 mChromeEventHandler
= nsnull
; // Forces Release
1111 mParentTarget
= nsnull
;
1113 nsGlobalWindow
*inner
= GetCurrentInnerWindowInternal();
1116 inner
->CleanUp(aIgnoreModalDialog
);
1119 DisableAccelerationUpdates();
1120 mHasAcceleration
= PR_FALSE
;
1122 if (mCleanMessageManager
) {
1123 NS_ABORT_IF_FALSE(mIsChrome
, "only chrome should have msg manager cleaned");
1124 nsGlobalChromeWindow
*asChrome
= static_cast<nsGlobalChromeWindow
*>(this);
1125 if (asChrome
->mMessageManager
) {
1126 static_cast<nsFrameMessageManager
*>(
1127 asChrome
->mMessageManager
.get())->Disconnect();
1131 mInnerWindowHolder
= nsnull
;
1132 mArguments
= nsnull
;
1133 mArgumentsLast
= nsnull
;
1134 mArgumentsOrigin
= nsnull
;
1136 CleanupCachedXBLHandlers(this);
1139 nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject
*>(this));
1144 nsGlobalWindow::ClearControllers()
1148 mControllers
->GetControllerCount(&count
);
1151 nsCOMPtr
<nsIController
> controller
;
1152 mControllers
->GetControllerAt(count
, getter_AddRefs(controller
));
1154 nsCOMPtr
<nsIControllerContext
> context
= do_QueryInterface(controller
);
1156 context
->SetCommandContext(nsnull
);
1159 mControllers
= nsnull
;
1165 nsGlobalWindow::TryClearWindowScope(nsISupports
*aWindow
)
1167 nsGlobalWindow
*window
=
1168 static_cast<nsGlobalWindow
*>(static_cast<nsIDOMWindow
*>(aWindow
));
1170 // This termination function might be called when any script evaluation in our
1171 // context terminated, even if there are other scripts in the stack. Thus, we
1172 // have to check again if a script is executing and post a new termination
1173 // function if necessary.
1174 window
->ClearScopeWhenAllScriptsStop();
1178 nsGlobalWindow::ClearScopeWhenAllScriptsStop()
1180 NS_ASSERTION(IsInnerWindow(), "Must be an inner window");
1182 // We cannot clear scope safely until all the scripts in our script context
1183 // stopped. This might be a long wait, for example if one script is busy
1184 // because it started a nested event loop for a modal dialog.
1185 nsIScriptContext
*jsscx
= GetContextInternal();
1186 if (jsscx
&& jsscx
->GetExecutingScript()) {
1187 // We ignore the return value because the only reason that we clear scope
1188 // here is to try to prevent leaks. Failing to clear scope might mean that
1189 // we'll leak more but if we don't have enough memory to allocate a
1190 // termination function we probably don't have to worry about this anyway.
1191 jsscx
->SetTerminationFunction(TryClearWindowScope
,
1192 static_cast<nsIDOMWindow
*>(this));
1196 NotifyWindowIDDestroyed("inner-window-destroyed");
1197 nsIScriptContext
*scx
= GetContextInternal();
1199 scx
->ClearScope(mJSObject
, PR_TRUE
);
1204 nsGlobalWindow::FreeInnerObjects(PRBool aClearScope
)
1206 NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
1208 // Kill all of the workers for this window.
1209 nsDOMThreadService
* dts
= nsDOMThreadService::get();
1211 nsIScriptContext
*scx
= GetContextInternal();
1213 JSContext
*cx
= scx
? (JSContext
*)scx
->GetNativeContext() : nsnull
;
1215 // Have to suspend this request here because CancelWorkersForGlobal will
1216 // lock until the worker has died and that could cause a deadlock.
1217 JSAutoSuspendRequest
asr(cx
);
1219 dts
->CancelWorkersForGlobal(static_cast<nsIScriptGlobalObject
*>(this));
1222 // Close all IndexedDB databases for this window.
1223 indexedDB::IndexedDatabaseManager
* idbManager
=
1224 indexedDB::IndexedDatabaseManager::Get();
1226 idbManager
->AbortCloseDatabasesForWindow(this);
1231 mChromeEventHandler
= nsnull
;
1233 if (mListenerManager
) {
1234 mListenerManager
->Disconnect();
1235 mListenerManager
= nsnull
;
1242 NS_ASSERTION(mDoc
, "Why is mDoc null?");
1244 // Remember the document's principal.
1245 mDocumentPrincipal
= mDoc
->NodePrincipal();
1250 nsCycleCollector_DEBUG_shouldBeFreed(nsCOMPtr
<nsISupports
>(do_QueryInterface(mDocument
)));
1253 // Make sure that this is called before we null out the document.
1254 NotifyDOMWindowDestroyed(this);
1256 // Remove our reference to the document and the document principal.
1260 if (mApplicationCache
) {
1261 static_cast<nsDOMOfflineResourceList
*>(mApplicationCache
.get())->Disconnect();
1262 mApplicationCache
= nsnull
;
1265 mIndexedDB
= nsnull
;
1268 ClearScopeWhenAllScriptsStop();
1271 if (mDummyJavaPluginOwner
) {
1272 // Tear down the dummy java plugin.
1274 // XXXjst: On a general note, should windows with java stuff in
1275 // them ever even make it into the fast-back cache?
1277 mDummyJavaPluginOwner
->Destroy();
1279 mDummyJavaPluginOwner
= nsnull
;
1282 CleanupCachedXBLHandlers(this);
1285 nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject
*>(this));
1289 //*****************************************************************************
1290 // nsGlobalWindow::nsISupports
1291 //*****************************************************************************
1293 #define OUTER_WINDOW_ONLY \
1294 if (IsOuterWindow()) {
1296 #define END_OUTER_WINDOW_ONLY \
1297 foundInterface = 0; \
1300 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindow
)
1302 DOMCI_DATA(Window
, nsGlobalWindow
)
1304 // QueryInterface implementation for nsGlobalWindow
1305 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow
)
1306 // Make sure this matches the cast in nsGlobalWindow::FromWrapper()
1307 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIScriptGlobalObject
)
1308 NS_INTERFACE_MAP_ENTRY(nsIDOMWindowInternal
)
1309 NS_INTERFACE_MAP_ENTRY(nsIDOMWindow
)
1310 NS_INTERFACE_MAP_ENTRY(nsIDOMWindow2
)
1311 NS_INTERFACE_MAP_ENTRY(nsIDOMJSWindow
)
1312 NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject
)
1313 NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal
)
1314 NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget
)
1315 NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget
)
1316 NS_INTERFACE_MAP_ENTRY(nsIDOM3EventTarget
)
1317 NS_INTERFACE_MAP_ENTRY(nsIDOMNSEventTarget
)
1318 NS_INTERFACE_MAP_ENTRY(nsPIDOMWindow
)
1319 NS_INTERFACE_MAP_ENTRY(nsIDOMViewCSS
)
1320 NS_INTERFACE_MAP_ENTRY(nsIDOMAbstractView
)
1321 NS_INTERFACE_MAP_ENTRY(nsIDOMStorageWindow
)
1322 NS_INTERFACE_MAP_ENTRY(nsIDOMStorageIndexedDB
)
1323 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
1324 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor
)
1325 NS_INTERFACE_MAP_ENTRY(nsIDOMWindow_2_0_BRANCH
)
1326 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Window
)
1328 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
1329 END_OUTER_WINDOW_ONLY
1330 NS_INTERFACE_MAP_END
1333 NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsGlobalWindow
, nsIScriptGlobalObject
)
1334 NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsGlobalWindow
,
1335 nsIScriptGlobalObject
)
1338 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGlobalWindow
)
1339 if (tmp
->mDoc
&& nsCCUncollectableMarker::InGeneration(
1340 cb
, tmp
->mDoc
->GetMarkedCCGeneration())) {
1341 return NS_SUCCESS_INTERRUPTED_TRAVERSE
;
1344 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext
)
1346 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mControllers
)
1347 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArguments
)
1348 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArgumentsLast
)
1350 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInnerWindowHolder
)
1351 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOuterWindow
)
1353 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOpenerScriptPrincipal
)
1354 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mListenerManager
)
1356 for (nsTimeout
* timeout
= tmp
->FirstTimeout();
1357 tmp
->IsTimeout(timeout
);
1358 timeout
= timeout
->Next()) {
1359 cb
.NoteNativeChild(timeout
, &NS_CYCLE_COLLECTION_NAME(nsTimeout
));
1362 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSessionStorage
)
1363 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mApplicationCache
)
1364 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocumentPrincipal
)
1365 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc
)
1367 // Traverse stuff from nsPIDOMWindow
1368 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChromeEventHandler
)
1369 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParentTarget
)
1370 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument
)
1371 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFrameElement
)
1373 // Traverse mDummyJavaPluginOwner
1374 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDummyJavaPluginOwner
)
1376 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFocusedNode
)
1378 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mPendingStorageEvents
)
1380 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
1382 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow
)
1383 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext
)
1385 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mControllers
)
1386 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mArguments
)
1387 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mArgumentsLast
)
1389 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInnerWindowHolder
)
1390 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOuterWindow
)
1392 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOpenerScriptPrincipal
)
1393 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListenerManager
)
1394 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSessionStorage
)
1395 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mApplicationCache
)
1396 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocumentPrincipal
)
1398 // Unlink stuff from nsPIDOMWindow
1399 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChromeEventHandler
)
1400 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParentTarget
)
1401 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument
)
1402 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFrameElement
)
1404 // Unlink mDummyJavaPluginOwner
1405 if (tmp
->mDummyJavaPluginOwner
) {
1406 tmp
->mDummyJavaPluginOwner
->Destroy();
1407 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDummyJavaPluginOwner
)
1410 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFocusedNode
)
1412 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mPendingStorageEvents
)
1414 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
1418 TraceData(TraceCallback
& aCallback
, void* aClosure
) :
1419 callback(aCallback
), closure(aClosure
) {}
1421 TraceCallback
& callback
;
1425 static PLDHashOperator
1426 TraceXBLHandlers(const void* aKey
, void* aData
, void* aClosure
)
1428 TraceData
* data
= static_cast<TraceData
*>(aClosure
);
1429 data
->callback(nsIProgrammingLanguage::JAVASCRIPT
, aData
, data
->closure
);
1430 return PL_DHASH_NEXT
;
1433 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindow
)
1434 if (tmp
->mCachedXBLPrototypeHandlers
.IsInitialized()) {
1435 TraceData
data(aCallback
, aClosure
);
1436 tmp
->mCachedXBLPrototypeHandlers
.EnumerateRead(TraceXBLHandlers
, &data
);
1438 NS_IMPL_CYCLE_COLLECTION_TRACE_END
1440 NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsGlobalWindow
)
1441 nsGlobalWindow::CleanupCachedXBLHandlers(tmp
);
1442 NS_IMPL_CYCLE_COLLECTION_ROOT_END
1444 //*****************************************************************************
1445 // nsGlobalWindow::nsIScriptGlobalObject
1446 //*****************************************************************************
1449 nsGlobalWindow::SetScriptContext(PRUint32 lang_id
, nsIScriptContext
*aScriptContext
)
1451 NS_ASSERTION(lang_id
== nsIProgrammingLanguage::JAVASCRIPT
,
1452 "We don't support this language ID");
1453 NS_ASSERTION(IsOuterWindow(), "Uh, SetScriptContext() called on inner window!");
1455 NS_ASSERTION(!aScriptContext
|| !mContext
, "Bad call to SetContext()!");
1457 if (aScriptContext
) {
1458 // should probably assert the context is clean???
1459 aScriptContext
->WillInitializeContext();
1461 nsresult rv
= aScriptContext
->InitContext();
1462 NS_ENSURE_SUCCESS(rv
, rv
);
1465 // This window is a [i]frame, don't bother GC'ing when the
1466 // frame's context is destroyed since a GC will happen when the
1467 // frameset or host document is destroyed anyway.
1469 aScriptContext
->SetGCOnDestruction(PR_FALSE
);
1473 mContext
= aScriptContext
;
1478 nsGlobalWindow::EnsureScriptEnvironment(PRUint32 aLangID
)
1480 NS_ASSERTION(aLangID
== nsIProgrammingLanguage::JAVASCRIPT
,
1481 "We don't support this language ID");
1482 FORWARD_TO_OUTER(EnsureScriptEnvironment
, (aLangID
), NS_ERROR_NOT_INITIALIZED
);
1487 NS_ASSERTION(!GetCurrentInnerWindowInternal(),
1488 "mJSObject is null, but we have an inner window?");
1490 nsCOMPtr
<nsIScriptRuntime
> scriptRuntime
;
1491 nsresult rv
= NS_GetScriptRuntimeByID(aLangID
, getter_AddRefs(scriptRuntime
));
1492 NS_ENSURE_SUCCESS(rv
, rv
);
1494 nsCOMPtr
<nsIScriptContext
> context
;
1495 rv
= scriptRuntime
->CreateContext(getter_AddRefs(context
));
1496 NS_ENSURE_SUCCESS(rv
, rv
);
1498 return SetScriptContext(aLangID
, context
);
1502 nsGlobalWindow::GetScriptContext(PRUint32 lang
)
1504 NS_ASSERTION(lang
== nsIProgrammingLanguage::JAVASCRIPT
,
1505 "We don't support this language ID");
1507 FORWARD_TO_OUTER(GetScriptContext
, (lang
), nsnull
);
1512 nsGlobalWindow::GetScriptGlobal(PRUint32 lang
)
1514 NS_ASSERTION(lang
== nsIProgrammingLanguage::JAVASCRIPT
,
1515 "We don't support this language ID");
1520 nsGlobalWindow::GetContext()
1522 FORWARD_TO_OUTER(GetContext
, (), nsnull
);
1524 // check GetContext is indeed identical to GetScriptContext()
1525 NS_ASSERTION(mContext
== GetScriptContext(nsIProgrammingLanguage::JAVASCRIPT
),
1526 "GetContext confused?");
1531 nsGlobalWindow::GetGlobalJSObject()
1533 NS_ASSERTION(mJSObject
== GetScriptGlobal(nsIProgrammingLanguage::JAVASCRIPT
),
1534 "GetGlobalJSObject confused?");
1535 return FastGetGlobalJSObject();
1539 nsGlobalWindow::WouldReuseInnerWindow(nsIDocument
*aNewDocument
)
1541 // We reuse the inner window when:
1542 // a. We are currently at our original document.
1543 // b. At least one of the following conditions are true:
1544 // -- We are not currently a content window (i.e., we're currently a chrome
1546 // -- The new document is the same as the old document. This means that we're
1547 // getting called from document.open().
1548 // -- The new document has the same origin as what we have loaded right now.
1550 if (!mDoc
|| !aNewDocument
) {
1554 if (!mDoc
->IsInitialDocument()) {
1558 NS_ASSERTION(IsAboutBlank(mDoc
->GetDocumentURI()),
1559 "How'd this happen?");
1561 // Great, we're the original document, check for one of the other
1563 if (mDoc
== aNewDocument
) {
1564 // aClearScopeHint is false.
1569 if (NS_SUCCEEDED(mDoc
->NodePrincipal()->Equals(aNewDocument
->NodePrincipal(),
1572 // The origin is the same.
1576 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(do_QueryInterface(mDocShell
));
1579 PRInt32 itemType
= nsIDocShellTreeItem::typeContent
;
1580 treeItem
->GetItemType(&itemType
);
1582 // If we're a chrome window, then we want to reuse the inner window.
1583 return itemType
== nsIDocShellTreeItem::typeChrome
;
1586 // No treeItem: don't reuse the current inner window.
1591 nsGlobalWindow::SetOpenerScriptPrincipal(nsIPrincipal
* aPrincipal
)
1593 FORWARD_TO_OUTER_VOID(SetOpenerScriptPrincipal
, (aPrincipal
));
1596 if (!mDoc
->IsInitialDocument()) {
1597 // We have a document already, and it's not the original one. Bail out.
1598 // Do NOT set mOpenerScriptPrincipal in this case, just to be safe.
1603 // We better have an about:blank document loaded at this point. Otherwise,
1604 // something is really weird.
1605 nsCOMPtr
<nsIURI
> uri
;
1606 mDoc
->NodePrincipal()->GetURI(getter_AddRefs(uri
));
1607 NS_ASSERTION(uri
&& IsAboutBlank(uri
) &&
1608 IsAboutBlank(mDoc
->GetDocumentURI()),
1609 "Unexpected original document");
1612 nsCOMPtr
<nsIDocShell_MOZILLA_2_0_BRANCH
> ds(do_QueryInterface(GetDocShell()));
1613 ds
->CreateAboutBlankContentViewer(aPrincipal
);
1614 mDoc
->SetIsInitialDocument(PR_TRUE
);
1619 nsGlobalWindow::GetOpenerScriptPrincipal()
1621 FORWARD_TO_OUTER(GetOpenerScriptPrincipal
, (), nsnull
);
1623 return mOpenerScriptPrincipal
;
1627 PushPopupControlState(PopupControlState aState
, PRBool aForce
)
1629 PopupControlState oldState
= gPopupControlState
;
1631 if (aState
< gPopupControlState
|| aForce
) {
1632 gPopupControlState
= aState
;
1639 PopPopupControlState(PopupControlState aState
)
1641 gPopupControlState
= aState
;
1645 nsGlobalWindow::PushPopupControlState(PopupControlState aState
,
1646 PRBool aForce
) const
1648 return ::PushPopupControlState(aState
, aForce
);
1652 nsGlobalWindow::PopPopupControlState(PopupControlState aState
) const
1654 ::PopPopupControlState(aState
);
1658 nsGlobalWindow::GetPopupControlState() const
1660 return gPopupControlState
;
1663 #define WINDOWSTATEHOLDER_IID \
1664 {0x0b917c3e, 0xbd50, 0x4683, {0xaf, 0xc9, 0xc7, 0x81, 0x07, 0xae, 0x33, 0x26}}
1666 class WindowStateHolder
: public nsISupports
1669 NS_DECLARE_STATIC_IID_ACCESSOR(WINDOWSTATEHOLDER_IID
)
1672 WindowStateHolder(nsGlobalWindow
*aWindow
,
1673 nsIXPConnectJSObjectHolder
*aHolder
,
1674 nsNavigator
*aNavigator
,
1675 nsIXPConnectJSObjectHolder
*aOuterProto
,
1676 nsIXPConnectJSObjectHolder
*aOuterRealProto
);
1678 nsGlobalWindow
* GetInnerWindow() { return mInnerWindow
; }
1679 nsIXPConnectJSObjectHolder
*GetInnerWindowHolder()
1680 { return mInnerWindowHolder
; }
1682 nsNavigator
* GetNavigator() { return mNavigator
; }
1683 nsIXPConnectJSObjectHolder
* GetOuterProto() { return mOuterProto
; }
1684 nsIXPConnectJSObjectHolder
* GetOuterRealProto() { return mOuterRealProto
; }
1686 void DidRestoreWindow()
1688 mInnerWindow
= nsnull
;
1690 mInnerWindowHolder
= nsnull
;
1691 mNavigator
= nsnull
;
1692 mOuterProto
= nsnull
;
1693 mOuterRealProto
= nsnull
;
1697 ~WindowStateHolder();
1699 nsGlobalWindow
*mInnerWindow
;
1700 // We hold onto this to make sure the inner window doesn't go away. The outer
1701 // window ends up recalculating it anyway.
1702 nsCOMPtr
<nsIXPConnectJSObjectHolder
> mInnerWindowHolder
;
1703 nsRefPtr
<nsNavigator
> mNavigator
;
1704 nsCOMPtr
<nsIXPConnectJSObjectHolder
> mOuterProto
;
1705 nsCOMPtr
<nsIXPConnectJSObjectHolder
> mOuterRealProto
;
1708 NS_DEFINE_STATIC_IID_ACCESSOR(WindowStateHolder
, WINDOWSTATEHOLDER_IID
)
1710 WindowStateHolder::WindowStateHolder(nsGlobalWindow
*aWindow
,
1711 nsIXPConnectJSObjectHolder
*aHolder
,
1712 nsNavigator
*aNavigator
,
1713 nsIXPConnectJSObjectHolder
*aOuterProto
,
1714 nsIXPConnectJSObjectHolder
*aOuterRealProto
)
1715 : mInnerWindow(aWindow
),
1716 mNavigator(aNavigator
),
1717 mOuterProto(aOuterProto
),
1718 mOuterRealProto(aOuterRealProto
)
1720 NS_PRECONDITION(aWindow
, "null window");
1721 NS_PRECONDITION(aWindow
->IsInnerWindow(), "Saving an outer window");
1723 mInnerWindowHolder
= aHolder
;
1725 aWindow
->SuspendTimeouts();
1728 WindowStateHolder::~WindowStateHolder()
1731 // This window was left in the bfcache and is now going away. We need to
1733 // Note that FreeInnerObjects may already have been called on the
1734 // inner window if its outer has already had SetDocShell(null)
1735 // called. In this case the contexts will all be null and the
1736 // PR_TRUE for aClearScope won't do anything; this is OK since
1737 // SetDocShell(null) already did it.
1738 mInnerWindow
->FreeInnerObjects(PR_TRUE
);
1742 NS_IMPL_ISUPPORTS1(WindowStateHolder
, WindowStateHolder
)
1745 nsGlobalWindow::SetNewDocument(nsIDocument
* aDocument
,
1746 nsISupports
* aState
,
1747 PRBool aForceReuseInnerWindow
)
1751 NS_PRECONDITION(mDocumentPrincipal
== nsnull
,
1752 "mDocumentPrincipal prematurely set!");
1755 NS_ERROR("SetNewDocument(null) called!");
1757 return NS_ERROR_INVALID_ARG
;
1760 if (IsInnerWindow()) {
1761 if (!mOuterWindow
) {
1762 return NS_ERROR_NOT_INITIALIZED
;
1765 // Refuse to set a new document if the call came from an inner
1766 // window that's not the current inner window.
1767 if (mOuterWindow
->GetCurrentInnerWindow() != this) {
1768 return NS_ERROR_NOT_AVAILABLE
;
1771 return GetOuterWindowInternal()->SetNewDocument(aDocument
, aState
,
1772 aForceReuseInnerWindow
);
1775 NS_PRECONDITION(IsOuterWindow(), "Must only be called on outer windows");
1778 // This outer is now getting its first inner, thaw the outer now
1779 // that it's ready and is getting an inner window.
1784 NS_ASSERTION(!GetCurrentInnerWindow() ||
1785 GetCurrentInnerWindow()->GetExtantDocument() == mDocument
,
1786 "Uh, mDocument doesn't match the current inner window "
1789 PRBool wouldReuseInnerWindow
= WouldReuseInnerWindow(aDocument
);
1790 if (aForceReuseInnerWindow
&&
1791 !wouldReuseInnerWindow
&&
1793 mDoc
->NodePrincipal() != aDocument
->NodePrincipal()) {
1794 NS_ERROR("Attempted forced inner window reuse while changing principal");
1795 return NS_ERROR_UNEXPECTED
;
1798 nsresult rv
= NS_OK
;
1800 nsCOMPtr
<nsIDocument
> oldDoc(do_QueryInterface(mDocument
));
1802 nsIScriptContext
*scx
= GetContextInternal();
1803 NS_ENSURE_TRUE(scx
, NS_ERROR_NOT_INITIALIZED
);
1805 JSContext
*cx
= (JSContext
*)scx
->GetNativeContext();
1806 #ifndef MOZ_DISABLE_DOMCRYPTO
1807 // clear smartcard events, our document has gone away.
1809 mCrypto
->SetEnableSmartCardEvents(PR_FALSE
);
1813 // First document load.
1815 // Get our private root. If it is equal to us, then we need to
1816 // attach our global key bindings that handles browser scrolling
1817 // and other browser commands.
1818 nsIDOMWindowInternal
*internal
= nsGlobalWindow::GetPrivateRoot();
1820 if (internal
== static_cast<nsIDOMWindowInternal
*>(this)) {
1821 nsCOMPtr
<nsIXBLService
> xblService
= do_GetService("@mozilla.org/xbl;1");
1823 nsCOMPtr
<nsPIDOMEventTarget
> piTarget
=
1824 do_QueryInterface(mChromeEventHandler
);
1825 xblService
->AttachGlobalKeyHandler(piTarget
);
1830 /* No mDocShell means we're already been partially closed down. When that
1831 happens, setting status isn't a big requirement, so don't. (Doesn't happen
1832 under normal circumstances, but bug 49615 describes a case.) */
1834 nsContentUtils::AddScriptRunner(
1835 NS_NewRunnableMethod(this, &nsGlobalWindow::ClearStatus
));
1837 PRBool reUseInnerWindow
= aForceReuseInnerWindow
|| wouldReuseInnerWindow
;
1839 // Remember the old document's principal.
1840 nsIPrincipal
*oldPrincipal
= nsnull
;
1842 oldPrincipal
= oldDoc
->NodePrincipal();
1845 // Drop our reference to the navigator object unless we're reusing
1846 // the existing inner window or the new document is from the same
1847 // origin as the old document.
1848 if (!reUseInnerWindow
&& mNavigator
&& oldPrincipal
) {
1850 rv
= oldPrincipal
->Equals(aDocument
->NodePrincipal(), &equal
);
1852 if (NS_FAILED(rv
) || !equal
) {
1853 // Different origins. Release the navigator object so it gets
1854 // recreated for the new document. The plugins or mime types
1855 // arrays may have changed. See bug 150087.
1856 mNavigator
->SetDocShell(nsnull
);
1858 mNavigator
= nsnull
;
1862 if (mNavigator
&& aDocument
!= oldDoc
) {
1863 // We didn't drop our reference to our old navigator object and
1864 // we're loading a new document. Notify the navigator object about
1865 // the new document load so that it can make sure it is ready for
1866 // the new document.
1868 mNavigator
->LoadingNewDocument();
1871 // Set mDocument even if this is an outer window to avoid
1872 // having to *always* reach into the inner window to find the
1874 mDocument
= do_QueryInterface(aDocument
);
1878 mLastOpenedURI
= aDocument
->GetDocumentURI();
1881 mContext
->WillInitializeContext();
1883 nsGlobalWindow
*currentInner
= GetCurrentInnerWindowInternal();
1885 nsRefPtr
<nsGlobalWindow
> newInnerWindow
;
1887 PRBool thisChrome
= IsChromeWindow();
1888 nsCOMPtr
<nsIXPConnectJSObjectHolder
> navigatorHolder
;
1891 PRBool isChrome
= PR_FALSE
;
1893 nsCxPusher cxPusher
;
1894 if (!cxPusher
.Push(cx
)) {
1895 return NS_ERROR_FAILURE
;
1898 JSAutoRequest
ar(cx
);
1900 nsCOMPtr
<WindowStateHolder
> wsh
= do_QueryInterface(aState
);
1901 NS_ASSERTION(!aState
|| wsh
, "What kind of weird state are you giving me here?");
1903 // Make sure to clear scope on the outer window *before* we
1904 // initialize the new inner window. If we don't, things
1905 // (Object.prototype etc) could leak from the old outer to the new
1907 mContext
->ClearScope(mJSObject
, PR_FALSE
);
1909 // This code should not be called during shutdown any more (now that
1910 // we don't ever call SetNewDocument(nsnull), so no need to null
1912 nsIXPConnect
*xpc
= nsContentUtils::XPConnect();
1913 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
1914 if (reUseInnerWindow
) {
1915 // We're reusing the current inner window.
1916 NS_ASSERTION(!currentInner
->IsFrozen(),
1917 "We should never be reusing a shared inner window");
1918 newInnerWindow
= currentInner
;
1920 if (aDocument
!= oldDoc
) {
1921 nsWindowSH::InvalidateGlobalScopePolluter(cx
, currentInner
->mJSObject
);
1925 newInnerWindow
= wsh
->GetInnerWindow();
1926 mInnerWindowHolder
= wsh
->GetInnerWindowHolder();
1928 NS_ASSERTION(newInnerWindow
, "Got a state without inner window");
1930 // These assignments addref.
1931 mNavigator
= wsh
->GetNavigator();
1934 // Update mNavigator's docshell pointer now.
1935 mNavigator
->SetDocShell(mDocShell
);
1936 mNavigator
->LoadingNewDocument();
1938 } else if (thisChrome
) {
1939 newInnerWindow
= new nsGlobalChromeWindow(this);
1941 } else if (mIsModalContentWindow
) {
1942 newInnerWindow
= new nsGlobalModalWindow(this);
1944 newInnerWindow
= new nsGlobalWindow(this);
1947 if (currentInner
&& currentInner
->mJSObject
) {
1948 if (mNavigator
&& !aState
) {
1949 // Hold on to the navigator wrapper so that we can set
1950 // window.navigator in the new window to point to the same
1951 // object (assuming we didn't change origins etc). See bug
1952 // 163645 for more on why we need this.
1954 nsIDOMNavigator
* navigator
=
1955 static_cast<nsIDOMNavigator
*>(mNavigator
.get());
1956 nsContentUtils::WrapNative(cx
, currentInner
->mJSObject
, navigator
,
1957 &NS_GET_IID(nsIDOMNavigator
), &nav
,
1958 getter_AddRefs(navigatorHolder
));
1963 // This is redundant if we're restoring from a previous inner window.
1964 nsIScriptGlobalObject
*sgo
=
1965 (nsIScriptGlobalObject
*)newInnerWindow
.get();
1967 // Freeze the outer window and null out the inner window so
1968 // that initializing classes on the new inner doesn't end up
1969 // reaching into the old inner window for classes etc.
1971 // [This happens with Object.prototype when XPConnect creates
1972 // a temporary global while initializing classes; the reason
1973 // being that xpconnect creates the temp global w/o a parent
1974 // and proto, which makes the JS engine look up classes in
1975 // cx->globalObject, i.e. this outer window].
1977 mInnerWindow
= nsnull
;
1980 mCreatingInnerWindow
= PR_TRUE
;
1981 // Every script context we are initialized with must create a
1983 void *&newGlobal
= (void *&)newInnerWindow
->mJSObject
;
1984 nsCOMPtr
<nsIXPConnectJSObjectHolder
> &holder
= mInnerWindowHolder
;
1985 rv
= mContext
->CreateNativeGlobalForInner(sgo
, isChrome
,
1986 aDocument
->NodePrincipal(),
1988 getter_AddRefs(holder
));
1989 NS_ASSERTION(NS_SUCCEEDED(rv
) && newGlobal
&& holder
,
1990 "Failed to get script global and holder");
1992 mCreatingInnerWindow
= PR_FALSE
;
1995 NS_ENSURE_SUCCESS(rv
, rv
);
1998 if (currentInner
&& currentInner
->mJSObject
) {
1999 PRBool termFuncSet
= PR_FALSE
;
2001 if (oldDoc
== aDocument
) {
2002 // Suspend the current context's request before Pop() resumes the old
2003 // context's request.
2004 JSAutoSuspendRequest
asr(cx
);
2006 // Pop our context here so that we get the correct one for the
2007 // termination function.
2010 JSContext
*oldCx
= nsContentUtils::GetCurrentJSContext();
2012 nsIScriptContext
*callerScx
;
2013 if (oldCx
&& (callerScx
= GetScriptContextFromJSContext(oldCx
))) {
2014 // We're called from document.open() (and document.open() is
2015 // called from JS), clear the scope etc in a termination
2016 // function on the calling context to prevent clearing the
2018 NS_ASSERTION(!currentInner
->IsFrozen(),
2019 "How does this opened window get into session history");
2021 JSAutoRequest
ar(oldCx
);
2023 callerScx
->SetTerminationFunction(ClearWindowScope
,
2024 static_cast<nsIDOMWindow
*>
2027 termFuncSet
= PR_TRUE
;
2030 // Re-push our context.
2034 // Don't clear scope on our current inner window if it's going to be
2035 // held in the bfcache.
2036 if (!currentInner
->IsFrozen()) {
2037 // Skip the ClearScope if we set a termination function to do
2038 // it ourselves, later.
2039 currentInner
->FreeInnerObjects(!termFuncSet
);
2043 mInnerWindow
= newInnerWindow
;
2046 mContext
->CreateOuterObject(this, newInnerWindow
);
2047 mContext
->DidInitializeContext();
2049 mJSObject
= (JSObject
*)mContext
->GetNativeGlobal();
2050 SetWrapper(mJSObject
);
2052 JSObject
*outerObject
=
2053 NS_NewOuterWindowProxy(cx
, newInnerWindow
->mJSObject
);
2055 NS_ERROR("out of memory");
2056 return NS_ERROR_FAILURE
;
2059 outerObject
= JS_TransplantObject(cx
, mJSObject
, outerObject
);
2061 NS_ERROR("unable to transplant wrappers, probably OOM");
2062 return NS_ERROR_FAILURE
;
2065 mJSObject
= outerObject
;
2066 SetWrapper(mJSObject
);
2069 JSAutoEnterCompartment ac
;
2070 if (!ac
.enter(cx
, mJSObject
)) {
2071 NS_ERROR("unable to enter a compartment");
2072 return NS_ERROR_FAILURE
;
2075 JS_SetParent(cx
, mJSObject
, newInnerWindow
->mJSObject
);
2077 mContext
->SetOuterObject(mJSObject
);
2081 JSAutoEnterCompartment ac
;
2082 if (!ac
.enter(cx
, mJSObject
)) {
2083 NS_ERROR("unable to enter a compartment");
2084 return NS_ERROR_FAILURE
;
2087 // XXX Not sure if this is needed.
2090 if (nsIXPConnectJSObjectHolder
*holder
= wsh
->GetOuterRealProto()) {
2091 holder
->GetJSObject(&proto
);
2096 if (!JS_SetPrototype(cx
, mJSObject
, proto
)) {
2097 NS_ERROR("can't set prototype");
2098 return NS_ERROR_FAILURE
;
2101 if (!JS_DefineProperty(cx
, newInnerWindow
->mJSObject
, "window",
2102 OBJECT_TO_JSVAL(mJSObject
),
2103 JS_PropertyStub
, JS_StrictPropertyStub
,
2104 JSPROP_ENUMERATE
| JSPROP_READONLY
| JSPROP_PERMANENT
)) {
2105 NS_ERROR("can't create the 'window' property");
2106 return NS_ERROR_FAILURE
;
2111 JSAutoEnterCompartment ac
;
2112 if (!ac
.enter(cx
, mJSObject
)) {
2113 NS_ERROR("unable to enter a compartment");
2114 return NS_ERROR_FAILURE
;
2117 if (!aState
&& !reUseInnerWindow
) {
2118 // Loading a new page and creating a new inner window, *not*
2119 // restoring from session history.
2121 // Now that both the the inner and outer windows are initialized
2122 // let the script context do its magic to hook them together.
2123 mContext
->ConnectToInner(newInnerWindow
, mJSObject
);
2125 nsCOMPtr
<nsIContent
> frame
= do_QueryInterface(GetFrameElementInternal());
2126 if (frame
&& frame
->GetOwnerDoc()) {
2127 nsPIDOMWindow
* parentWindow
= frame
->GetOwnerDoc()->GetWindow();
2128 if (parentWindow
&& parentWindow
->TimeoutSuspendCount()) {
2129 SuspendTimeouts(parentWindow
->TimeoutSuspendCount());
2134 // Tell the contexts we have completed setting up the doc.
2135 // Add an extra ref in case we release mContext during GC.
2136 nsCOMPtr
<nsIScriptContext
> kungFuDeathGrip(mContext
);
2137 nsCOMPtr
<nsIDOMDocument
> dd(do_QueryInterface(aDocument
));
2138 mContext
->DidSetDocument(dd
, newInnerWindow
->mJSObject
);
2140 // Now that the prototype is all set up, install the global scope
2141 // polluter. This must happen after the above prototype fixup. If
2142 // the GSP was to be installed on the inner window's real
2143 // prototype (as it would be if this was done before the prototype
2144 // fixup above) we would end up holding the GSP alive (through
2145 // XPConnect's internal marking of wrapper prototypes) as long as
2146 // the inner window was around, and if the GSP had properties on
2147 // it that held an element alive we'd hold the document alive,
2148 // which could hold event handlers alive, which hold the context
2151 if ((!reUseInnerWindow
|| aDocument
!= oldDoc
) && !aState
) {
2152 nsCOMPtr
<nsIHTMLDocument
> html_doc(do_QueryInterface(mDocument
));
2153 nsWindowSH::InstallGlobalScopePolluter(cx
, newInnerWindow
->mJSObject
,
2158 aDocument
->SetScriptGlobalObject(newInnerWindow
);
2162 if (reUseInnerWindow
) {
2163 if (newInnerWindow
->mDoc
!= aDocument
) {
2164 newInnerWindow
->mDocument
= do_QueryInterface(aDocument
);
2165 newInnerWindow
->mDoc
= aDocument
;
2167 // We're reusing the inner window for a new document. In this
2168 // case we don't clear the inner window's scope, but we must
2169 // make sure the cached document property gets updated.
2171 // XXXmarkh - tell other languages about this?
2172 ::JS_DeleteProperty(cx
, currentInner
->mJSObject
, "document");
2175 rv
= newInnerWindow
->InnerSetNewDocument(aDocument
);
2176 NS_ENSURE_SUCCESS(rv
, rv
);
2178 // Initialize DOM classes etc on the inner window.
2179 rv
= mContext
->InitClasses(newInnerWindow
->mJSObject
);
2180 NS_ENSURE_SUCCESS(rv
, rv
);
2182 if (navigatorHolder
) {
2183 JS_ASSERT(JSVAL_IS_OBJECT(nav
));
2185 if (JSVAL_TO_OBJECT(nav
)->compartment() == newInnerWindow
->mJSObject
->compartment()) {
2186 // Restore window.navigator onto the new inner window.
2188 ::JS_DefineProperty(cx
, newInnerWindow
->mJSObject
, "navigator",
2189 nav
, nsnull
, nsnull
,
2190 JSPROP_ENUMERATE
| JSPROP_PERMANENT
|
2193 // The Navigator's prototype object keeps a reference to the
2194 // window in which it was first created and can thus cause that
2195 // window to stay alive for too long. Reparenting it here allows
2196 // the window to be collected sooner.
2197 nsIDOMNavigator
* navigator
=
2198 static_cast<nsIDOMNavigator
*>(mNavigator
);
2201 ReparentWrappedNativeIfFound(cx
, JSVAL_TO_OBJECT(nav
),
2202 newInnerWindow
->mJSObject
,
2204 getter_AddRefs(navigatorHolder
));
2210 newInnerWindow
->DefineArgumentsProperty(mArguments
);
2211 newInnerWindow
->mArguments
= mArguments
;
2212 newInnerWindow
->mArgumentsOrigin
= mArgumentsOrigin
;
2214 mArguments
= nsnull
;
2215 mArgumentsOrigin
= nsnull
;
2218 // Give the new inner window our chrome event handler (since it
2219 // doesn't have one).
2220 newInnerWindow
->mChromeEventHandler
= mChromeEventHandler
;
2224 mContext
->DidInitializeContext();
2226 if (newInnerWindow
&& !newInnerWindow
->mHasNotifiedGlobalCreated
&& mDoc
) {
2227 // We should probably notify. However if this is the, arguably bad,
2228 // situation when we're creating a temporary non-chrome-about-blank
2229 // document in a chrome docshell, don't notify just yet. Instead wait
2230 // until we have a real chrome doc.
2231 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(do_QueryInterface(mDocShell
));
2232 PRInt32 itemType
= nsIDocShellTreeItem::typeContent
;
2234 treeItem
->GetItemType(&itemType
);
2237 if (itemType
!= nsIDocShellTreeItem::typeChrome
||
2238 nsContentUtils::IsSystemPrincipal(mDoc
->NodePrincipal())) {
2239 newInnerWindow
->mHasNotifiedGlobalCreated
= PR_TRUE
;
2240 nsContentUtils::AddScriptRunner(
2241 NS_NewRunnableMethod(this, &nsGlobalWindow::DispatchDOMWindowCreated
));
2249 nsGlobalWindow::DispatchDOMWindowCreated()
2251 if (!mDoc
|| !mDocument
) {
2255 // Fire DOMWindowCreated at chrome event listeners
2256 nsContentUtils::DispatchChromeEvent(mDoc
, mDocument
, NS_LITERAL_STRING("DOMWindowCreated"),
2257 PR_TRUE
/* bubbles */,
2258 PR_FALSE
/* not cancellable */);
2260 nsCOMPtr
<nsIObserverService
> observerService
=
2261 mozilla::services::GetObserverService();
2262 if (observerService
) {
2263 nsAutoString origin
;
2264 nsIPrincipal
* principal
= mDoc
->NodePrincipal();
2265 nsContentUtils::GetUTFOrigin(principal
, origin
);
2267 NotifyObservers(static_cast<nsIDOMWindow
*>(this),
2268 nsContentUtils::IsSystemPrincipal(principal
) ?
2269 "chrome-document-global-created" :
2270 "content-document-global-created",
2276 nsGlobalWindow::ClearStatus()
2278 SetStatus(EmptyString());
2279 SetDefaultStatus(EmptyString());
2283 nsGlobalWindow::InnerSetNewDocument(nsIDocument
* aDocument
)
2285 NS_PRECONDITION(IsInnerWindow(), "Must only be called on inner windows");
2288 if (aDocument
&& gDOMLeakPRLog
&&
2289 PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
2290 nsIURI
*uri
= aDocument
->GetDocumentURI();
2294 PR_LogPrint("DOMWINDOW %p SetNewDocument %s", this, spec
.get());
2298 mDocument
= do_QueryInterface(aDocument
);
2300 mLocalStorage
= nsnull
;
2301 mSessionStorage
= nsnull
;
2304 mLastOpenedURI
= aDocument
->GetDocumentURI();
2307 // Clear our mutation bitfield.
2314 nsGlobalWindow::SetDocShell(nsIDocShell
* aDocShell
)
2316 NS_ASSERTION(IsOuterWindow(), "Uh, SetDocShell() called on inner window!");
2318 if (aDocShell
== mDocShell
)
2321 // SetDocShell(nsnull) means the window is being torn down. Drop our
2322 // reference to the script context, allowing it to be deleted
2323 // later. Meanwhile, keep our weak reference to the script object
2324 // (mJSObject) so that it can be retrieved later (until it is
2325 // finalized by the JS GC).
2328 NS_ASSERTION(PR_CLIST_IS_EMPTY(&mTimeouts
),
2329 "Uh, outer window holds timeouts!");
2331 // Call FreeInnerObjects on all inner windows, not just the current
2332 // one, since some could be held by WindowStateHolder objects that
2334 for (nsRefPtr
<nsGlobalWindow
> inner
= (nsGlobalWindow
*)PR_LIST_HEAD(this);
2336 inner
= (nsGlobalWindow
*)PR_NEXT_LINK(inner
)) {
2337 NS_ASSERTION(!inner
->mOuterWindow
|| inner
->mOuterWindow
== this,
2338 "bad outer window pointer");
2339 inner
->FreeInnerObjects(PR_TRUE
);
2342 // Make sure that this is called before we null out the document.
2343 NotifyDOMWindowDestroyed(this);
2345 NotifyWindowIDDestroyed("outer-window-destroyed");
2347 nsGlobalWindow
*currentInner
= GetCurrentInnerWindowInternal();
2350 NS_ASSERTION(mDoc
, "Must have doc!");
2352 // Remember the document's principal.
2353 mDocumentPrincipal
= mDoc
->NodePrincipal();
2355 // Release our document reference
2361 mContext
->ClearScope(mJSObject
, PR_TRUE
);
2366 mChromeEventHandler
= nsnull
; // force release now
2369 // We got no new document after someone called
2370 // SetArguments(), drop our reference to the arguments.
2371 mArguments
= nsnull
;
2372 mArgumentsLast
= nsnull
;
2373 mArgumentsOrigin
= nsnull
;
2378 mContext
->FinalizeContext();
2383 nsCycleCollector_DEBUG_shouldBeFreed(mContext
);
2384 nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject
*>(this));
2388 mDocShell
= aDocShell
; // Weak Reference
2391 mNavigator
->SetDocShell(aDocShell
);
2393 mFrames
->SetDocShell(aDocShell
);
2395 mScreen
->SetDocShell(aDocShell
);
2397 // tell our member elements about the new browserwindow
2398 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2399 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2401 mMenubar
->SetWebBrowserChrome(browserChrome
);
2404 mToolbar
->SetWebBrowserChrome(browserChrome
);
2407 mLocationbar
->SetWebBrowserChrome(browserChrome
);
2410 mPersonalbar
->SetWebBrowserChrome(browserChrome
);
2413 mStatusbar
->SetWebBrowserChrome(browserChrome
);
2416 mScrollbars
->SetWebBrowserChrome(browserChrome
);
2420 MaybeForgiveSpamCount();
2423 // Get our enclosing chrome shell and retrieve its global window impl, so
2424 // that we can do some forwarding to the chrome document.
2425 nsCOMPtr
<nsIDOMEventTarget
> chromeEventHandler
;
2426 mDocShell
->GetChromeEventHandler(getter_AddRefs(chromeEventHandler
));
2427 mChromeEventHandler
= do_QueryInterface(chromeEventHandler
);
2428 if (!mChromeEventHandler
) {
2429 // We have no chrome event handler. If we have a parent,
2430 // get our chrome event handler from the parent. If
2431 // we don't have a parent, then we need to make a new
2432 // window root object that will function as a chrome event
2433 // handler and receive all events that occur anywhere inside
2435 nsCOMPtr
<nsIDOMWindow
> parentWindow
;
2436 GetParent(getter_AddRefs(parentWindow
));
2437 if (parentWindow
.get() != static_cast<nsIDOMWindow
*>(this)) {
2438 nsCOMPtr
<nsPIDOMWindow
> piWindow(do_QueryInterface(parentWindow
));
2439 mChromeEventHandler
= piWindow
->GetChromeEventHandler();
2441 else NS_NewWindowRoot(this, getter_AddRefs(mChromeEventHandler
));
2447 nsGlobalWindow::SetOpenerWindow(nsIDOMWindowInternal
* aOpener
,
2448 PRBool aOriginalOpener
)
2450 FORWARD_TO_OUTER_VOID(SetOpenerWindow
, (aOpener
, aOriginalOpener
));
2452 NS_ASSERTION(!aOriginalOpener
|| !mSetOpenerWindowCalled
,
2453 "aOriginalOpener is true, but not first call to "
2454 "SetOpenerWindow!");
2455 NS_ASSERTION(aOpener
|| !aOriginalOpener
,
2456 "Shouldn't set mHadOriginalOpener if aOpener is null");
2458 mOpener
= do_GetWeakReference(aOpener
);
2459 NS_ASSERTION(mOpener
|| !aOpener
, "Opener must support weak references!");
2461 if (aOriginalOpener
) {
2462 mHadOriginalOpener
= PR_TRUE
;
2466 mSetOpenerWindowCalled
= PR_TRUE
;
2471 nsGlobalWindow::UpdateParentTarget()
2473 nsCOMPtr
<nsIFrameLoaderOwner
> flo
= do_QueryInterface(mChromeEventHandler
);
2475 nsRefPtr
<nsFrameLoader
> fl
= flo
->GetFrameLoader();
2477 mParentTarget
= fl
->GetTabChildGlobalAsEventTarget();
2480 if (!mParentTarget
) {
2481 mParentTarget
= mChromeEventHandler
;
2486 nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor
& aVisitor
)
2488 NS_PRECONDITION(IsInnerWindow(), "PreHandleEvent is used on outer window!?");
2489 static PRUint32 count
= 0;
2490 PRUint32 msg
= aVisitor
.mEvent
->message
;
2492 aVisitor
.mCanHandle
= PR_TRUE
;
2493 aVisitor
.mForceContentDispatch
= PR_TRUE
; //FIXME! Bug 329119
2494 if ((msg
== NS_MOUSE_MOVE
) && gEntropyCollector
) {
2495 //Chances are this counter will overflow during the life of the
2496 //process, but that's OK for our case. Means we get a little
2498 if (count
++ % 100 == 0) {
2499 //Since the high bits seem to be zero's most of the time,
2500 //let's only take the lowest half of the point structure.
2503 myCoord
[0] = aVisitor
.mEvent
->refPoint
.x
;
2504 myCoord
[1] = aVisitor
.mEvent
->refPoint
.y
;
2505 gEntropyCollector
->RandomUpdate((void*)myCoord
, sizeof(myCoord
));
2506 gEntropyCollector
->RandomUpdate((void*)&(aVisitor
.mEvent
->time
),
2509 } else if (msg
== NS_RESIZE_EVENT
) {
2510 mIsHandlingResizeEvent
= PR_TRUE
;
2511 } else if (msg
== NS_MOUSE_BUTTON_DOWN
&&
2512 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2513 gMouseDown
= PR_TRUE
;
2514 } else if (msg
== NS_MOUSE_BUTTON_UP
&&
2515 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2516 gMouseDown
= PR_FALSE
;
2517 if (gDragServiceDisabled
) {
2518 nsCOMPtr
<nsIDragService
> ds
=
2519 do_GetService("@mozilla.org/widget/dragservice;1");
2521 gDragServiceDisabled
= PR_FALSE
;
2527 aVisitor
.mParentTarget
= GetParentTarget();
2532 nsGlobalWindow::DialogOpenAttempted()
2534 nsGlobalWindow
*topWindow
= GetTop();
2536 NS_ERROR("DialogOpenAttempted() called without a top window?");
2541 topWindow
= topWindow
->GetCurrentInnerWindowInternal();
2543 topWindow
->mLastDialogQuitTime
.IsNull() ||
2544 nsContentUtils::IsCallerTrustedForCapability("UniversalXPConnect")) {
2548 TimeDuration
dialogDuration(TimeStamp::Now() -
2549 topWindow
->mLastDialogQuitTime
);
2551 if (dialogDuration
.ToSeconds() <
2552 nsContentUtils::GetIntPref("dom.successive_dialog_time_limit",
2553 SUCCESSIVE_DIALOG_TIME_LIMIT
)) {
2554 topWindow
->mDialogAbuseCount
++;
2556 return (topWindow
->GetPopupControlState() > openAllowed
||
2557 topWindow
->mDialogAbuseCount
> MAX_DIALOG_COUNT
);
2560 topWindow
->mDialogAbuseCount
= 0;
2566 nsGlobalWindow::AreDialogsBlocked()
2568 nsGlobalWindow
*topWindow
= GetTop();
2570 NS_ASSERTION(!mDocShell
, "AreDialogsBlocked() called without a top window?");
2575 topWindow
= topWindow
->GetCurrentInnerWindowInternal();
2577 return !topWindow
||
2578 (topWindow
->mDialogDisabled
&&
2579 (topWindow
->GetPopupControlState() > openAllowed
||
2580 topWindow
->mDialogAbuseCount
>= MAX_DIALOG_COUNT
));
2584 nsGlobalWindow::ConfirmDialogAllowed()
2586 FORWARD_TO_OUTER(ConfirmDialogAllowed
, (), NS_ERROR_NOT_INITIALIZED
);
2588 NS_ENSURE_TRUE(mDocShell
, false);
2589 nsCOMPtr
<nsIPromptService
> promptSvc
=
2590 do_GetService("@mozilla.org/embedcomp/prompt-service;1");
2592 if (!DialogOpenAttempted() || !promptSvc
) {
2596 // Reset popup state while opening a modal dialog, and firing events
2597 // about the dialog, to prevent the current state from being active
2598 // the whole time a modal dialog is open.
2599 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
2601 PRBool disableDialog
= PR_FALSE
;
2602 nsXPIDLString label
, title
;
2603 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
2604 "ScriptDialogLabel", label
);
2605 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
2606 "ScriptDialogPreventTitle", title
);
2607 promptSvc
->Confirm(this, title
.get(), label
.get(), &disableDialog
);
2608 if (disableDialog
) {
2609 PreventFurtherDialogs();
2617 nsGlobalWindow::PreventFurtherDialogs()
2619 nsGlobalWindow
*topWindow
= GetTop();
2621 NS_ERROR("PreventFurtherDialogs() called without a top window?");
2626 topWindow
= topWindow
->GetCurrentInnerWindowInternal();
2629 topWindow
->mDialogDisabled
= PR_TRUE
;
2633 nsGlobalWindow::PostHandleEvent(nsEventChainPostVisitor
& aVisitor
)
2635 NS_PRECONDITION(IsInnerWindow(), "PostHandleEvent is used on outer window!?");
2637 // Return early if there is nothing to do.
2638 switch (aVisitor
.mEvent
->message
) {
2639 case NS_RESIZE_EVENT
:
2640 case NS_PAGE_UNLOAD
:
2647 /* mChromeEventHandler and mContext go dangling in the middle of this
2648 function under some circumstances (events that destroy the window)
2649 without this addref. */
2650 nsCOMPtr
<nsPIDOMEventTarget
> kungFuDeathGrip1(mChromeEventHandler
);
2651 nsCOMPtr
<nsIScriptContext
> kungFuDeathGrip2(GetContextInternal());
2653 if (aVisitor
.mEvent
->message
== NS_RESIZE_EVENT
) {
2654 mIsHandlingResizeEvent
= PR_FALSE
;
2655 } else if (aVisitor
.mEvent
->message
== NS_PAGE_UNLOAD
&&
2656 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2657 // Execute bindingdetached handlers before we tear ourselves
2660 NS_ASSERTION(mDoc
, "Must have doc");
2661 mDoc
->BindingManager()->ExecuteDetachedHandlers();
2663 mIsDocumentLoaded
= PR_FALSE
;
2664 } else if (aVisitor
.mEvent
->message
== NS_LOAD
&&
2665 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2666 // This is page load event since load events don't propagate to |window|.
2667 // @see nsDocument::PreHandleEvent.
2668 mIsDocumentLoaded
= PR_TRUE
;
2670 nsCOMPtr
<nsIContent
> content(do_QueryInterface(GetFrameElementInternal()));
2671 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
=
2672 do_QueryInterface(GetDocShell());
2674 PRInt32 itemType
= nsIDocShellTreeItem::typeChrome
;
2677 treeItem
->GetItemType(&itemType
);
2680 if (content
&& GetParentInternal() &&
2681 itemType
!= nsIDocShellTreeItem::typeChrome
) {
2682 // If we're not in chrome, or at a chrome boundary, fire the
2683 // onload event for the frame element.
2685 nsEventStatus status
= nsEventStatus_eIgnore
;
2686 nsEvent
event(NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
), NS_LOAD
);
2687 event
.flags
|= NS_EVENT_FLAG_CANT_BUBBLE
;
2689 // Most of the time we could get a pres context to pass in here,
2690 // but not always (i.e. if this window is not shown there won't
2691 // be a pres context available). Since we're not firing a GUI
2692 // event we don't need a pres context anyway so we just pass
2693 // null as the pres context all the time here.
2695 nsEventDispatcher::Dispatch(content
, nsnull
, &event
, nsnull
, &status
);
2703 nsGlobalWindow::DispatchDOMEvent(nsEvent
* aEvent
,
2704 nsIDOMEvent
* aDOMEvent
,
2705 nsPresContext
* aPresContext
,
2706 nsEventStatus
* aEventStatus
)
2709 nsEventDispatcher::DispatchDOMEvent(static_cast<nsPIDOMWindow
*>(this),
2710 aEvent
, aDOMEvent
, aPresContext
,
2715 nsGlobalWindow::OnFinalize(PRUint32 aLangID
, void *aObject
)
2717 NS_ASSERTION(aLangID
== nsIProgrammingLanguage::JAVASCRIPT
,
2718 "We don't support this language ID");
2720 if (aObject
== mJSObject
) {
2726 nsGlobalWindow::SetScriptsEnabled(PRBool aEnabled
, PRBool aFireTimeouts
)
2728 FORWARD_TO_INNER_VOID(SetScriptsEnabled
, (aEnabled
, aFireTimeouts
));
2730 if (aEnabled
&& aFireTimeouts
) {
2731 // Scripts are enabled (again?) on this context, run timeouts that
2732 // fired on this context while scripts were disabled.
2733 void (nsGlobalWindow::*run
)() = &nsGlobalWindow::RunTimeout
;
2734 NS_DispatchToCurrentThread(NS_NewRunnableMethod(this, run
));
2739 nsGlobalWindow::SetArguments(nsIArray
*aArguments
, nsIPrincipal
*aOrigin
)
2741 FORWARD_TO_OUTER(SetArguments
, (aArguments
, aOrigin
),
2742 NS_ERROR_NOT_INITIALIZED
);
2744 // Hold on to the arguments so that we can re-set them once the next
2745 // document is loaded.
2746 mArguments
= aArguments
;
2747 mArgumentsOrigin
= aOrigin
;
2749 nsGlobalWindow
*currentInner
= GetCurrentInnerWindowInternal();
2751 if (!mIsModalContentWindow
) {
2752 mArgumentsLast
= aArguments
;
2753 } else if (currentInner
) {
2754 // SetArguments() is being called on a modal content window that
2755 // already has an inner window. This can happen when loading
2756 // javascript: URIs as modal content dialogs. In this case, we'll
2757 // set up the dialog window, both inner and outer, before we call
2758 // SetArguments() on the window, so to deal with that, make sure
2759 // here that the arguments are propagated to the inner window.
2761 currentInner
->mArguments
= aArguments
;
2762 currentInner
->mArgumentsOrigin
= aOrigin
;
2765 return currentInner
?
2766 currentInner
->DefineArgumentsProperty(aArguments
) : NS_OK
;
2770 nsGlobalWindow::DefineArgumentsProperty(nsIArray
*aArguments
)
2773 nsIScriptContext
*ctx
= GetOuterWindowInternal()->mContext
;
2774 NS_ENSURE_TRUE(aArguments
&& ctx
&&
2775 (cx
= (JSContext
*)ctx
->GetNativeContext()),
2776 NS_ERROR_NOT_INITIALIZED
);
2778 if (mIsModalContentWindow
) {
2779 // Modal content windows don't have an "arguments" property, they
2780 // have a "dialogArguments" property which is handled
2781 // separately. See nsWindowSH::NewResolve().
2786 return GetContextInternal()->SetProperty(mJSObject
, "arguments", aArguments
);
2789 //*****************************************************************************
2790 // nsGlobalWindow::nsIScriptObjectPrincipal
2791 //*****************************************************************************
2794 nsGlobalWindow::GetPrincipal()
2797 // If we have a document, get the principal from the document
2798 return mDoc
->NodePrincipal();
2801 if (mDocumentPrincipal
) {
2802 return mDocumentPrincipal
;
2805 // If we don't have a principal and we don't have a document we
2806 // ask the parent window for the principal. This can happen when
2807 // loading a frameset that has a <frame src="javascript:xxx">, in
2808 // that case the global window is used in JS before we've loaded
2809 // a document into the window.
2811 nsCOMPtr
<nsIScriptObjectPrincipal
> objPrincipal
=
2812 do_QueryInterface(GetParentInternal());
2815 return objPrincipal
->GetPrincipal();
2821 //*****************************************************************************
2822 // nsGlobalWindow::nsIDOMWindow
2823 //*****************************************************************************
2826 nsGlobalWindow::GetDocument(nsIDOMDocument
** aDocument
)
2828 // This method *should* forward calls to the outer window, but since
2829 // there's nothing here that *depends* on anything in the outer
2830 // (GetDocShell() eliminates that dependency), we won't do that to
2831 // avoid the extra virtual function call.
2833 // lazily instantiate an about:blank document if necessary, and if
2834 // we have what it takes to do so. Note that domdoc here is the same
2835 // thing as our mDocument, but we don't have to explicitly set the
2836 // member variable because the docshell has already called
2837 // SetNewDocument().
2838 nsIDocShell
*docShell
;
2839 if (!mDocument
&& (docShell
= GetDocShell()))
2840 nsCOMPtr
<nsIDOMDocument
> domdoc(do_GetInterface(docShell
));
2842 NS_IF_ADDREF(*aDocument
= mDocument
);
2847 //*****************************************************************************
2848 // nsGlobalWindow::nsIDOMWindowInternal
2849 //*****************************************************************************
2852 nsGlobalWindow::GetWindow(nsIDOMWindowInternal
** aWindow
)
2854 FORWARD_TO_OUTER(GetWindow
, (aWindow
), NS_ERROR_NOT_INITIALIZED
);
2856 *aWindow
= static_cast<nsIDOMWindowInternal
*>(this);
2857 NS_ADDREF(*aWindow
);
2862 nsGlobalWindow::GetSelf(nsIDOMWindowInternal
** aWindow
)
2864 FORWARD_TO_OUTER(GetSelf
, (aWindow
), NS_ERROR_NOT_INITIALIZED
);
2866 *aWindow
= static_cast<nsIDOMWindowInternal
*>(this);
2867 NS_ADDREF(*aWindow
);
2872 nsGlobalWindow::GetNavigator(nsIDOMNavigator
** aNavigator
)
2874 FORWARD_TO_OUTER(GetNavigator
, (aNavigator
), NS_ERROR_NOT_INITIALIZED
);
2876 *aNavigator
= nsnull
;
2879 mNavigator
= new nsNavigator(mDocShell
);
2881 return NS_ERROR_OUT_OF_MEMORY
;
2885 NS_ADDREF(*aNavigator
= mNavigator
);
2891 nsGlobalWindow::GetScreen(nsIDOMScreen
** aScreen
)
2893 FORWARD_TO_OUTER(GetScreen
, (aScreen
), NS_ERROR_NOT_INITIALIZED
);
2897 if (!mScreen
&& mDocShell
) {
2898 mScreen
= new nsScreen(mDocShell
);
2900 return NS_ERROR_OUT_OF_MEMORY
;
2904 NS_IF_ADDREF(*aScreen
= mScreen
);
2910 nsGlobalWindow::GetHistory(nsIDOMHistory
** aHistory
)
2912 FORWARD_TO_INNER(GetHistory
, (aHistory
), NS_ERROR_NOT_INITIALIZED
);
2917 mHistory
= new nsHistory(this);
2919 return NS_ERROR_OUT_OF_MEMORY
;
2923 NS_IF_ADDREF(*aHistory
= mHistory
);
2928 nsGlobalWindow::GetParent(nsIDOMWindow
** aParent
)
2930 FORWARD_TO_OUTER(GetParent
, (aParent
), NS_ERROR_NOT_INITIALIZED
);
2936 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
2937 NS_ENSURE_TRUE(docShellAsItem
, NS_ERROR_FAILURE
);
2939 nsCOMPtr
<nsIDocShellTreeItem
> parent
;
2940 docShellAsItem
->GetSameTypeParent(getter_AddRefs(parent
));
2943 nsCOMPtr
<nsIScriptGlobalObject
> globalObject(do_GetInterface(parent
));
2944 NS_ENSURE_SUCCESS(CallQueryInterface(globalObject
.get(), aParent
),
2948 *aParent
= static_cast<nsIDOMWindowInternal
*>(this);
2949 NS_ADDREF(*aParent
);
2955 nsGlobalWindow::GetTop(nsIDOMWindow
** aTop
)
2957 FORWARD_TO_OUTER(GetTop
, (aTop
), NS_ERROR_NOT_INITIALIZED
);
2961 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
2962 nsCOMPtr
<nsIDocShellTreeItem
> root
;
2963 docShellAsItem
->GetSameTypeRootTreeItem(getter_AddRefs(root
));
2966 nsCOMPtr
<nsIDOMWindow
> top(do_GetInterface(root
));
2975 nsGlobalWindow::GetContent(nsIDOMWindow
** aContent
)
2977 FORWARD_TO_OUTER(GetContent
, (aContent
), NS_ERROR_NOT_INITIALIZED
);
2981 nsCOMPtr
<nsIDocShellTreeItem
> primaryContent
;
2983 if (!nsContentUtils::IsCallerChrome()) {
2984 // If we're called by non-chrome code, make sure we don't return
2985 // the primary content window if the calling tab is hidden. In
2986 // such a case we return the same-type root in the hidden tab,
2987 // which is "good enough", for now.
2988 nsCOMPtr
<nsIBaseWindow
> baseWin(do_QueryInterface(mDocShell
));
2991 PRBool visible
= PR_FALSE
;
2992 baseWin
->GetVisibility(&visible
);
2995 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(do_QueryInterface(mDocShell
));
2997 treeItem
->GetSameTypeRootTreeItem(getter_AddRefs(primaryContent
));
3002 if (!primaryContent
) {
3003 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
3004 GetTreeOwner(getter_AddRefs(treeOwner
));
3005 NS_ENSURE_TRUE(treeOwner
, NS_ERROR_FAILURE
);
3007 treeOwner
->GetPrimaryContentShell(getter_AddRefs(primaryContent
));
3010 nsCOMPtr
<nsIDOMWindowInternal
> domWindow(do_GetInterface(primaryContent
));
3011 NS_IF_ADDREF(*aContent
= domWindow
);
3017 nsGlobalWindow::GetPrompter(nsIPrompt
** aPrompt
)
3019 FORWARD_TO_OUTER(GetPrompter
, (aPrompt
), NS_ERROR_NOT_INITIALIZED
);
3022 return NS_ERROR_FAILURE
;
3024 nsCOMPtr
<nsIPrompt
> prompter(do_GetInterface(mDocShell
));
3025 NS_ENSURE_TRUE(prompter
, NS_ERROR_NO_INTERFACE
);
3027 NS_ADDREF(*aPrompt
= prompter
);
3032 nsGlobalWindow::GetMenubar(nsIDOMBarProp
** aMenubar
)
3034 FORWARD_TO_OUTER(GetMenubar
, (aMenubar
), NS_ERROR_NOT_INITIALIZED
);
3039 mMenubar
= new nsMenubarProp();
3041 return NS_ERROR_OUT_OF_MEMORY
;
3044 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3045 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3047 mMenubar
->SetWebBrowserChrome(browserChrome
);
3050 NS_ADDREF(*aMenubar
= mMenubar
);
3056 nsGlobalWindow::GetToolbar(nsIDOMBarProp
** aToolbar
)
3058 FORWARD_TO_OUTER(GetToolbar
, (aToolbar
), NS_ERROR_NOT_INITIALIZED
);
3063 mToolbar
= new nsToolbarProp();
3065 return NS_ERROR_OUT_OF_MEMORY
;
3068 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3069 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3071 mToolbar
->SetWebBrowserChrome(browserChrome
);
3074 NS_ADDREF(*aToolbar
= mToolbar
);
3080 nsGlobalWindow::GetLocationbar(nsIDOMBarProp
** aLocationbar
)
3082 FORWARD_TO_OUTER(GetLocationbar
, (aLocationbar
), NS_ERROR_NOT_INITIALIZED
);
3084 *aLocationbar
= nsnull
;
3086 if (!mLocationbar
) {
3087 mLocationbar
= new nsLocationbarProp();
3088 if (!mLocationbar
) {
3089 return NS_ERROR_OUT_OF_MEMORY
;
3092 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3093 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3095 mLocationbar
->SetWebBrowserChrome(browserChrome
);
3098 NS_ADDREF(*aLocationbar
= mLocationbar
);
3104 nsGlobalWindow::GetPersonalbar(nsIDOMBarProp
** aPersonalbar
)
3106 FORWARD_TO_OUTER(GetPersonalbar
, (aPersonalbar
), NS_ERROR_NOT_INITIALIZED
);
3108 *aPersonalbar
= nsnull
;
3110 if (!mPersonalbar
) {
3111 mPersonalbar
= new nsPersonalbarProp();
3112 if (!mPersonalbar
) {
3113 return NS_ERROR_OUT_OF_MEMORY
;
3116 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3117 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3119 mPersonalbar
->SetWebBrowserChrome(browserChrome
);
3122 NS_ADDREF(*aPersonalbar
= mPersonalbar
);
3128 nsGlobalWindow::GetStatusbar(nsIDOMBarProp
** aStatusbar
)
3130 FORWARD_TO_OUTER(GetStatusbar
, (aStatusbar
), NS_ERROR_NOT_INITIALIZED
);
3132 *aStatusbar
= nsnull
;
3135 mStatusbar
= new nsStatusbarProp();
3137 return NS_ERROR_OUT_OF_MEMORY
;
3140 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3141 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3143 mStatusbar
->SetWebBrowserChrome(browserChrome
);
3146 NS_ADDREF(*aStatusbar
= mStatusbar
);
3152 nsGlobalWindow::GetScrollbars(nsIDOMBarProp
** aScrollbars
)
3154 FORWARD_TO_OUTER(GetScrollbars
, (aScrollbars
), NS_ERROR_NOT_INITIALIZED
);
3156 *aScrollbars
= nsnull
;
3159 mScrollbars
= new nsScrollbarsProp(this);
3161 return NS_ERROR_OUT_OF_MEMORY
;
3164 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3165 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3167 mScrollbars
->SetWebBrowserChrome(browserChrome
);
3170 NS_ADDREF(*aScrollbars
= mScrollbars
);
3176 nsGlobalWindow::GetClosed(PRBool
* aClosed
)
3178 FORWARD_TO_OUTER(GetClosed
, (aClosed
), NS_ERROR_NOT_INITIALIZED
);
3180 // If someone called close(), or if we don't have a docshell, we're
3182 *aClosed
= mIsClosed
|| !mDocShell
;
3188 nsGlobalWindow::GetFrames(nsIDOMWindowCollection
** aFrames
)
3190 FORWARD_TO_OUTER(GetFrames
, (aFrames
), NS_ERROR_NOT_INITIALIZED
);
3194 if (!mFrames
&& mDocShell
) {
3195 mFrames
= new nsDOMWindowList(mDocShell
);
3197 return NS_ERROR_OUT_OF_MEMORY
;
3201 *aFrames
= static_cast<nsIDOMWindowCollection
*>(mFrames
);
3202 NS_IF_ADDREF(*aFrames
);
3207 nsGlobalWindow::GetApplicationCache(nsIDOMOfflineResourceList
**aApplicationCache
)
3209 FORWARD_TO_INNER(GetApplicationCache
, (aApplicationCache
), NS_ERROR_UNEXPECTED
);
3211 NS_ENSURE_ARG_POINTER(aApplicationCache
);
3213 if (!mApplicationCache
) {
3214 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(GetDocShell()));
3216 return NS_ERROR_FAILURE
;
3219 nsCOMPtr
<nsIURI
> uri
;
3220 nsresult rv
= webNav
->GetCurrentURI(getter_AddRefs(uri
));
3221 NS_ENSURE_SUCCESS(rv
, rv
);
3223 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(mDocument
);
3224 nsCOMPtr
<nsIURI
> manifestURI
;
3225 nsContentUtils::GetOfflineAppManifest(doc
, getter_AddRefs(manifestURI
));
3227 nsIScriptContext
* scriptContext
= GetContext();
3228 NS_ENSURE_STATE(scriptContext
);
3230 nsRefPtr
<nsDOMOfflineResourceList
> applicationCache
=
3231 new nsDOMOfflineResourceList(manifestURI
, uri
, this, scriptContext
);
3232 NS_ENSURE_TRUE(applicationCache
, NS_ERROR_OUT_OF_MEMORY
);
3234 applicationCache
->Init();
3236 mApplicationCache
= applicationCache
;
3239 NS_IF_ADDREF(*aApplicationCache
= mApplicationCache
);
3245 nsGlobalWindow::CreateBlobURL(nsIDOMBlob
* aBlob
, nsAString
& aURL
)
3247 return NS_ERROR_NOT_IMPLEMENTED
;
3251 nsGlobalWindow::RevokeBlobURL(const nsAString
& aURL
)
3253 return NS_ERROR_NOT_IMPLEMENTED
;
3257 nsGlobalWindow::GetCrypto(nsIDOMCrypto
** aCrypto
)
3259 #ifdef MOZ_DISABLE_DOMCRYPTO
3260 return NS_ERROR_NOT_IMPLEMENTED
;
3262 FORWARD_TO_OUTER(GetCrypto
, (aCrypto
), NS_ERROR_NOT_INITIALIZED
);
3265 mCrypto
= do_CreateInstance(kCryptoContractID
);
3268 NS_IF_ADDREF(*aCrypto
= mCrypto
);
3275 nsGlobalWindow::GetPkcs11(nsIDOMPkcs11
** aPkcs11
)
3282 nsGlobalWindow::GetControllers(nsIControllers
** aResult
)
3284 FORWARD_TO_OUTER(GetControllers
, (aResult
), NS_ERROR_NOT_INITIALIZED
);
3286 if (!mControllers
) {
3288 mControllers
= do_CreateInstance(kXULControllersCID
, &rv
);
3289 NS_ENSURE_SUCCESS(rv
, rv
);
3291 // Add in the default controller
3292 nsCOMPtr
<nsIController
> controller
= do_CreateInstance(
3293 NS_WINDOWCONTROLLER_CONTRACTID
, &rv
);
3294 NS_ENSURE_SUCCESS(rv
, rv
);
3296 mControllers
->InsertControllerAt(0, controller
);
3297 nsCOMPtr
<nsIControllerContext
> controllerContext
= do_QueryInterface(controller
);
3298 if (!controllerContext
) return NS_ERROR_FAILURE
;
3300 controllerContext
->SetCommandContext(static_cast<nsIDOMWindow
*>(this));
3303 *aResult
= mControllers
;
3304 NS_ADDREF(*aResult
);
3309 nsGlobalWindow::GetOpener(nsIDOMWindowInternal
** aOpener
)
3311 FORWARD_TO_OUTER(GetOpener
, (aOpener
), NS_ERROR_NOT_INITIALIZED
);
3315 nsCOMPtr
<nsPIDOMWindow
> opener
= do_QueryReferent(mOpener
);
3320 // First, check if we were called from a privileged chrome script
3321 if (nsContentUtils::IsCallerTrustedForRead()) {
3322 NS_ADDREF(*aOpener
= opener
);
3326 nsCOMPtr
<nsPIDOMWindow
> openerPwin(do_QueryInterface(opener
));
3331 // First, ensure that we're not handing back a chrome window.
3332 nsGlobalWindow
*win
= static_cast<nsGlobalWindow
*>(openerPwin
.get());
3333 if (win
->IsChromeWindow()) {
3337 // We don't want to reveal the opener if the opener is a mail window,
3338 // because opener can be used to spoof the contents of a message (bug 105050).
3339 // So, we look in the opener's root docshell to see if it's a mail window.
3340 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem
=
3341 do_QueryInterface(openerPwin
->GetDocShell());
3343 if (docShellAsItem
) {
3344 nsCOMPtr
<nsIDocShellTreeItem
> openerRootItem
;
3345 docShellAsItem
->GetRootTreeItem(getter_AddRefs(openerRootItem
));
3346 nsCOMPtr
<nsIDocShell
> openerRootDocShell(do_QueryInterface(openerRootItem
));
3347 if (openerRootDocShell
) {
3349 nsresult rv
= openerRootDocShell
->GetAppType(&appType
);
3350 if (NS_SUCCEEDED(rv
) && appType
!= nsIDocShell::APP_TYPE_MAIL
) {
3356 NS_IF_ADDREF(*aOpener
);
3361 nsGlobalWindow::SetOpener(nsIDOMWindowInternal
* aOpener
)
3363 // check if we were called from a privileged chrome script.
3364 // If not, opener is settable only to null.
3365 if (aOpener
&& !nsContentUtils::IsCallerTrustedForWrite()) {
3369 SetOpenerWindow(aOpener
, PR_FALSE
);
3375 nsGlobalWindow::GetStatus(nsAString
& aStatus
)
3377 FORWARD_TO_OUTER(GetStatus
, (aStatus
), NS_ERROR_NOT_INITIALIZED
);
3384 nsGlobalWindow::SetStatus(const nsAString
& aStatus
)
3386 FORWARD_TO_OUTER(SetStatus
, (aStatus
), NS_ERROR_NOT_INITIALIZED
);
3389 * If caller is not chrome and dom.disable_window_status_change is true,
3390 * prevent setting window.status by exiting early
3393 if (!CanSetProperty("dom.disable_window_status_change")) {
3399 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3400 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3402 browserChrome
->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT
,
3403 PromiseFlatString(aStatus
).get());
3410 nsGlobalWindow::GetDefaultStatus(nsAString
& aDefaultStatus
)
3412 FORWARD_TO_OUTER(GetDefaultStatus
, (aDefaultStatus
),
3413 NS_ERROR_NOT_INITIALIZED
);
3415 aDefaultStatus
= mDefaultStatus
;
3420 nsGlobalWindow::SetDefaultStatus(const nsAString
& aDefaultStatus
)
3422 FORWARD_TO_OUTER(SetDefaultStatus
, (aDefaultStatus
),
3423 NS_ERROR_NOT_INITIALIZED
);
3426 * If caller is not chrome and dom.disable_window_status_change is true,
3427 * prevent setting window.defaultStatus by exiting early
3430 if (!CanSetProperty("dom.disable_window_status_change")) {
3434 mDefaultStatus
= aDefaultStatus
;
3436 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3437 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3438 if (browserChrome
) {
3439 browserChrome
->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT_DEFAULT
,
3440 PromiseFlatString(aDefaultStatus
).get());
3447 nsGlobalWindow::GetName(nsAString
& aName
)
3449 FORWARD_TO_OUTER(GetName
, (aName
), NS_ERROR_NOT_INITIALIZED
);
3452 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
3454 docShellAsItem
->GetName(getter_Copies(name
));
3461 nsGlobalWindow::SetName(const nsAString
& aName
)
3463 FORWARD_TO_OUTER(SetName
, (aName
), NS_ERROR_NOT_INITIALIZED
);
3465 nsresult result
= NS_OK
;
3466 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
3468 result
= docShellAsItem
->SetName(PromiseFlatString(aName
).get());
3472 // Helper functions used by many methods below.
3474 nsGlobalWindow::DevToCSSIntPixels(PRInt32 px
)
3477 return px
; // assume 1:1
3479 nsRefPtr
<nsPresContext
> presContext
;
3480 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3484 return presContext
->DevPixelsToIntCSSPixels(px
);
3488 nsGlobalWindow::CSSToDevIntPixels(PRInt32 px
)
3491 return px
; // assume 1:1
3493 nsRefPtr
<nsPresContext
> presContext
;
3494 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3498 return presContext
->CSSPixelsToDevPixels(px
);
3502 nsGlobalWindow::DevToCSSIntPixels(nsIntSize px
)
3505 return px
; // assume 1:1
3507 nsRefPtr
<nsPresContext
> presContext
;
3508 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3513 presContext
->DevPixelsToIntCSSPixels(px
.width
),
3514 presContext
->DevPixelsToIntCSSPixels(px
.height
));
3518 nsGlobalWindow::CSSToDevIntPixels(nsIntSize px
)
3521 return px
; // assume 1:1
3523 nsRefPtr
<nsPresContext
> presContext
;
3524 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3529 presContext
->CSSPixelsToDevPixels(px
.width
),
3530 presContext
->CSSPixelsToDevPixels(px
.height
));
3535 nsGlobalWindow::GetInnerWidth(PRInt32
* aInnerWidth
)
3537 FORWARD_TO_OUTER(GetInnerWidth
, (aInnerWidth
), NS_ERROR_NOT_INITIALIZED
);
3539 NS_ENSURE_STATE(mDocShell
);
3541 EnsureSizeUpToDate();
3543 nsRefPtr
<nsPresContext
> presContext
;
3544 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3547 nsRect shellArea
= presContext
->GetVisibleArea();
3548 *aInnerWidth
= nsPresContext::AppUnitsToIntCSSPixels(shellArea
.width
);
3557 nsGlobalWindow::SetInnerWidth(PRInt32 aInnerWidth
)
3559 FORWARD_TO_OUTER(SetInnerWidth
, (aInnerWidth
), NS_ERROR_NOT_INITIALIZED
);
3561 NS_ENSURE_STATE(mDocShell
);
3564 * If caller is not chrome and the user has not explicitly exempted the site,
3565 * prevent setting window.innerWidth by exiting early
3567 if (!CanMoveResizeWindows() || IsFrame()) {
3571 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&aInnerWidth
, nsnull
),
3575 nsRefPtr
<nsIPresShell
> presShell
;
3576 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
3577 nsCOMPtr
<nsIPresShell_MOZILLA_2_0_BRANCH
> presShell20
=
3578 do_QueryInterface(presShell
);
3580 if (presShell20
&& presShell20
->GetIsViewportOverridden())
3585 nsRefPtr
<nsPresContext
> presContext
;
3586 presContext
= presShell
->GetPresContext();
3588 nsRect shellArea
= presContext
->GetVisibleArea();
3589 height
= shellArea
.height
;
3590 width
= nsPresContext::CSSPixelsToAppUnits(aInnerWidth
);
3591 return SetCSSViewportWidthAndHeight(width
, height
);
3598 nsCOMPtr
<nsIBaseWindow
> docShellAsWin(do_QueryInterface(mDocShell
));
3599 docShellAsWin
->GetSize(&width
, &height
);
3600 width
= CSSToDevIntPixels(aInnerWidth
);
3601 return SetDocShellWidthAndHeight(width
, height
);
3606 nsGlobalWindow::GetInnerHeight(PRInt32
* aInnerHeight
)
3608 FORWARD_TO_OUTER(GetInnerHeight
, (aInnerHeight
), NS_ERROR_NOT_INITIALIZED
);
3610 NS_ENSURE_STATE(mDocShell
);
3612 EnsureSizeUpToDate();
3614 nsRefPtr
<nsPresContext
> presContext
;
3615 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3618 nsRect shellArea
= presContext
->GetVisibleArea();
3619 *aInnerHeight
= nsPresContext::AppUnitsToIntCSSPixels(shellArea
.height
);
3627 nsGlobalWindow::SetInnerHeight(PRInt32 aInnerHeight
)
3629 FORWARD_TO_OUTER(SetInnerHeight
, (aInnerHeight
), NS_ERROR_NOT_INITIALIZED
);
3631 NS_ENSURE_STATE(mDocShell
);
3634 * If caller is not chrome and the user has not explicitly exempted the site,
3635 * prevent setting window.innerHeight by exiting early
3637 if (!CanMoveResizeWindows() || IsFrame()) {
3641 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(nsnull
, &aInnerHeight
),
3644 nsRefPtr
<nsIPresShell
> presShell
;
3645 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
3646 nsCOMPtr
<nsIPresShell_MOZILLA_2_0_BRANCH
> presShell20
=
3647 do_QueryInterface(presShell
);
3649 if (presShell20
&& presShell20
->GetIsViewportOverridden())
3654 nsRefPtr
<nsPresContext
> presContext
;
3655 presContext
= presShell
->GetPresContext();
3657 nsRect shellArea
= presContext
->GetVisibleArea();
3658 width
= shellArea
.width
;
3659 height
= nsPresContext::CSSPixelsToAppUnits(aInnerHeight
);
3660 return SetCSSViewportWidthAndHeight(width
, height
);
3667 nsCOMPtr
<nsIBaseWindow
> docShellAsWin(do_QueryInterface(mDocShell
));
3668 docShellAsWin
->GetSize(&width
, &height
);
3669 height
= CSSToDevIntPixels(aInnerHeight
);
3670 return SetDocShellWidthAndHeight(width
, height
);
3675 nsGlobalWindow::GetOuterSize(nsIntSize
* aSizeCSSPixels
)
3677 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3678 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3679 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3681 nsGlobalWindow
* rootWindow
=
3682 static_cast<nsGlobalWindow
*>(GetPrivateRoot());
3684 rootWindow
->FlushPendingNotifications(Flush_Layout
);
3687 nsIntSize sizeDevPixels
;
3688 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetSize(&sizeDevPixels
.width
,
3689 &sizeDevPixels
.height
),
3692 *aSizeCSSPixels
= DevToCSSIntPixels(sizeDevPixels
);
3697 nsGlobalWindow::GetOuterWidth(PRInt32
* aOuterWidth
)
3699 FORWARD_TO_OUTER(GetOuterWidth
, (aOuterWidth
), NS_ERROR_NOT_INITIALIZED
);
3701 nsIntSize sizeCSSPixels
;
3702 nsresult rv
= GetOuterSize(&sizeCSSPixels
);
3703 NS_ENSURE_SUCCESS(rv
, rv
);
3705 *aOuterWidth
= sizeCSSPixels
.width
;
3710 nsGlobalWindow::GetOuterHeight(PRInt32
* aOuterHeight
)
3712 FORWARD_TO_OUTER(GetOuterHeight
, (aOuterHeight
), NS_ERROR_NOT_INITIALIZED
);
3714 nsIntSize sizeCSSPixels
;
3715 nsresult rv
= GetOuterSize(&sizeCSSPixels
);
3716 NS_ENSURE_SUCCESS(rv
, rv
);
3718 *aOuterHeight
= sizeCSSPixels
.height
;
3723 nsGlobalWindow::SetOuterSize(PRInt32 aLengthCSSPixels
, PRBool aIsWidth
)
3726 * If caller is not chrome and the user has not explicitly exempted the site,
3727 * prevent setting window.outerWidth by exiting early
3730 if (!CanMoveResizeWindows() || IsFrame()) {
3734 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3735 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3736 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3738 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(
3739 aIsWidth
? &aLengthCSSPixels
: nsnull
,
3740 aIsWidth
? nsnull
: &aLengthCSSPixels
),
3743 PRInt32 width
, height
;
3744 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetSize(&width
, &height
), NS_ERROR_FAILURE
);
3746 PRInt32 lengthDevPixels
= CSSToDevIntPixels(aLengthCSSPixels
);
3748 width
= lengthDevPixels
;
3750 height
= lengthDevPixels
;
3752 return treeOwnerAsWin
->SetSize(width
, height
, PR_TRUE
);
3756 nsGlobalWindow::SetOuterWidth(PRInt32 aOuterWidth
)
3758 FORWARD_TO_OUTER(SetOuterWidth
, (aOuterWidth
), NS_ERROR_NOT_INITIALIZED
);
3760 return SetOuterSize(aOuterWidth
, PR_TRUE
);
3764 nsGlobalWindow::SetOuterHeight(PRInt32 aOuterHeight
)
3766 FORWARD_TO_OUTER(SetOuterHeight
, (aOuterHeight
), NS_ERROR_NOT_INITIALIZED
);
3768 return SetOuterSize(aOuterHeight
, PR_FALSE
);
3772 nsGlobalWindow::GetScreenX(PRInt32
* aScreenX
)
3774 FORWARD_TO_OUTER(GetScreenX
, (aScreenX
), NS_ERROR_NOT_INITIALIZED
);
3776 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3777 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3778 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3782 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3785 *aScreenX
= DevToCSSIntPixels(x
);
3790 nsGlobalWindow::GetInnerScreenRect()
3795 nsGlobalWindow
* rootWindow
=
3796 static_cast<nsGlobalWindow
*>(GetPrivateRoot());
3798 rootWindow
->FlushPendingNotifications(Flush_Layout
);
3801 nsCOMPtr
<nsIPresShell
> presShell
;
3802 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
3805 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
3809 return rootFrame
->GetScreenRectInAppUnits();
3813 nsGlobalWindow::GetMozInnerScreenX(float* aScreenX
)
3815 FORWARD_TO_OUTER(GetMozInnerScreenX
, (aScreenX
), NS_ERROR_NOT_INITIALIZED
);
3817 nsRect r
= GetInnerScreenRect();
3818 *aScreenX
= nsPresContext::AppUnitsToFloatCSSPixels(r
.x
);
3823 nsGlobalWindow::GetMozInnerScreenY(float* aScreenY
)
3825 FORWARD_TO_OUTER(GetMozInnerScreenY
, (aScreenY
), NS_ERROR_NOT_INITIALIZED
);
3827 nsRect r
= GetInnerScreenRect();
3828 *aScreenY
= nsPresContext::AppUnitsToFloatCSSPixels(r
.y
);
3833 nsGlobalWindow::GetMozPaintCount(PRUint64
* aResult
)
3835 FORWARD_TO_OUTER(GetMozPaintCount
, (aResult
), NS_ERROR_NOT_INITIALIZED
);
3842 nsCOMPtr
<nsIPresShell
> presShell
;
3843 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
3847 *aResult
= presShell
->GetPaintCount();
3852 nsGlobalWindow::MozRequestAnimationFrame(nsIAnimationFrameListener
* aListener
)
3854 FORWARD_TO_INNER(MozRequestAnimationFrame
, (aListener
),
3855 NS_ERROR_NOT_INITIALIZED
);
3861 mDoc
->ScheduleBeforePaintEvent(aListener
);
3866 nsGlobalWindow::GetMozAnimationStartTime(PRInt64
*aTime
)
3868 FORWARD_TO_INNER(GetMozAnimationStartTime
, (aTime
), NS_ERROR_NOT_INITIALIZED
);
3871 nsIPresShell
* presShell
= mDoc
->GetShell();
3873 *aTime
= presShell
->GetPresContext()->RefreshDriver()->
3874 MostRecentRefreshEpochTime() / PR_USEC_PER_MSEC
;
3879 // If all else fails, just be compatible with Date.now()
3880 *aTime
= JS_Now() / PR_USEC_PER_MSEC
;
3885 nsGlobalWindow::SetScreenX(PRInt32 aScreenX
)
3887 FORWARD_TO_OUTER(SetScreenX
, (aScreenX
), NS_ERROR_NOT_INITIALIZED
);
3890 * If caller is not chrome and the user has not explicitly exempted the site,
3891 * prevent setting window.screenX by exiting early
3894 if (!CanMoveResizeWindows() || IsFrame()) {
3898 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3899 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3900 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3902 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&aScreenX
, nsnull
),
3906 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3909 x
= CSSToDevIntPixels(aScreenX
);
3911 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(x
, y
),
3918 nsGlobalWindow::GetScreenY(PRInt32
* aScreenY
)
3920 FORWARD_TO_OUTER(GetScreenY
, (aScreenY
), NS_ERROR_NOT_INITIALIZED
);
3922 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3923 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3924 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3928 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3931 *aScreenY
= DevToCSSIntPixels(y
);
3936 nsGlobalWindow::SetScreenY(PRInt32 aScreenY
)
3938 FORWARD_TO_OUTER(SetScreenY
, (aScreenY
), NS_ERROR_NOT_INITIALIZED
);
3941 * If caller is not chrome and the user has not explicitly exempted the site,
3942 * prevent setting window.screenY by exiting early
3945 if (!CanMoveResizeWindows() || IsFrame()) {
3949 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3950 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3951 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3953 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(nsnull
, &aScreenY
),
3957 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3960 y
= CSSToDevIntPixels(aScreenY
);
3962 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(x
, y
),
3968 // NOTE: Arguments to this function should have values scaled to
3969 // CSS pixels, not device pixels.
3971 nsGlobalWindow::CheckSecurityWidthAndHeight(PRInt32
* aWidth
, PRInt32
* aHeight
)
3974 if (!nsContentUtils::IsCallerTrustedForWrite()) {
3975 // if attempting to resize the window, hide any open popups
3976 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
3977 nsContentUtils::HidePopupsInDocument(doc
);
3981 // This one is easy. Just ensure the variable is greater than 100;
3982 if ((aWidth
&& *aWidth
< 100) || (aHeight
&& *aHeight
< 100)) {
3983 // Check security state for use in determing window dimensions
3985 if (!nsContentUtils::IsCallerTrustedForWrite()) {
3987 if (aWidth
&& *aWidth
< 100) {
3990 if (aHeight
&& *aHeight
< 100) {
3999 // NOTE: Arguments to this function should have values in device pixels
4001 nsGlobalWindow::SetDocShellWidthAndHeight(PRInt32 aInnerWidth
, PRInt32 aInnerHeight
)
4003 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
4004 NS_ENSURE_TRUE(docShellAsItem
, NS_ERROR_FAILURE
);
4006 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
4007 docShellAsItem
->GetTreeOwner(getter_AddRefs(treeOwner
));
4008 NS_ENSURE_TRUE(treeOwner
, NS_ERROR_FAILURE
);
4010 NS_ENSURE_SUCCESS(treeOwner
->SizeShellTo(docShellAsItem
, aInnerWidth
, aInnerHeight
),
4016 // NOTE: Arguments to this function should have values in app units
4018 nsGlobalWindow::SetCSSViewportWidthAndHeight(nscoord aInnerWidth
, nscoord aInnerHeight
)
4020 nsRefPtr
<nsPresContext
> presContext
;
4021 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
4023 nsRect shellArea
= presContext
->GetVisibleArea();
4024 shellArea
.height
= aInnerHeight
;
4025 shellArea
.width
= aInnerWidth
;
4027 presContext
->SetVisibleArea(shellArea
);
4031 // NOTE: Arguments to this function should have values scaled to
4032 // CSS pixels, not device pixels.
4034 nsGlobalWindow::CheckSecurityLeftAndTop(PRInt32
* aLeft
, PRInt32
* aTop
)
4036 // This one is harder. We have to get the screen size and window dimensions.
4038 // Check security state for use in determing window dimensions
4040 if (!nsContentUtils::IsCallerTrustedForWrite()) {
4042 // if attempting to move the window, hide any open popups
4043 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
4044 nsContentUtils::HidePopupsInDocument(doc
);
4047 nsGlobalWindow
* rootWindow
=
4048 static_cast<nsGlobalWindow
*>(GetPrivateRoot());
4050 rootWindow
->FlushPendingNotifications(Flush_Layout
);
4053 nsCOMPtr
<nsIBaseWindow
> treeOwner
;
4054 GetTreeOwner(getter_AddRefs(treeOwner
));
4056 nsCOMPtr
<nsIDOMScreen
> screen
;
4057 GetScreen(getter_AddRefs(screen
));
4059 if (treeOwner
&& screen
) {
4060 PRInt32 screenLeft
, screenTop
, screenWidth
, screenHeight
;
4061 PRInt32 winLeft
, winTop
, winWidth
, winHeight
;
4063 // Get the window size
4064 treeOwner
->GetPositionAndSize(&winLeft
, &winTop
, &winWidth
, &winHeight
);
4066 // convert those values to CSS pixels
4067 // XXX four separate retrievals of the prescontext
4068 winLeft
= DevToCSSIntPixels(winLeft
);
4069 winTop
= DevToCSSIntPixels(winTop
);
4070 winWidth
= DevToCSSIntPixels(winWidth
);
4071 winHeight
= DevToCSSIntPixels(winHeight
);
4073 // Get the screen dimensions
4074 // XXX This should use nsIScreenManager once it's fully fleshed out.
4075 screen
->GetAvailLeft(&screenLeft
);
4076 screen
->GetAvailWidth(&screenWidth
);
4077 screen
->GetAvailHeight(&screenHeight
);
4078 #if defined(XP_MAC) || defined(XP_MACOSX)
4079 /* The mac's coordinate system is different from the assumed Windows'
4080 system. It offsets by the height of the menubar so that a window
4081 placed at (0,0) will be entirely visible. Unfortunately that
4082 correction is made elsewhere (in Widget) and the meaning of
4083 the Avail... coordinates is overloaded. Here we allow a window
4084 to be placed at (0,0) because it does make sense to do so.
4086 screen
->GetTop(&screenTop
);
4088 screen
->GetAvailTop(&screenTop
);
4092 if (screenLeft
+screenWidth
< *aLeft
+winWidth
)
4093 *aLeft
= screenLeft
+screenWidth
- winWidth
;
4094 if (screenLeft
> *aLeft
)
4095 *aLeft
= screenLeft
;
4098 if (screenTop
+screenHeight
< *aTop
+winHeight
)
4099 *aTop
= screenTop
+screenHeight
- winHeight
;
4100 if (screenTop
> *aTop
)
4115 nsGlobalWindow::GetPageXOffset(PRInt32
* aPageXOffset
)
4117 return GetScrollX(aPageXOffset
);
4121 nsGlobalWindow::GetPageYOffset(PRInt32
* aPageYOffset
)
4123 return GetScrollY(aPageYOffset
);
4127 nsGlobalWindow::GetScrollMaxXY(PRInt32
* aScrollMaxX
, PRInt32
* aScrollMaxY
)
4129 FORWARD_TO_OUTER(GetScrollMaxXY
, (aScrollMaxX
, aScrollMaxY
),
4130 NS_ERROR_NOT_INITIALIZED
);
4132 FlushPendingNotifications(Flush_Layout
);
4133 nsIScrollableFrame
*sf
= GetScrollFrame();
4137 nsRect scrollRange
= sf
->GetScrollRange();
4140 *aScrollMaxX
= NS_MAX(0,
4141 (PRInt32
)floor(nsPresContext::AppUnitsToFloatCSSPixels(scrollRange
.XMost())));
4143 *aScrollMaxY
= NS_MAX(0,
4144 (PRInt32
)floor(nsPresContext::AppUnitsToFloatCSSPixels(scrollRange
.YMost())));
4150 nsGlobalWindow::GetScrollMaxX(PRInt32
* aScrollMaxX
)
4152 NS_ENSURE_ARG_POINTER(aScrollMaxX
);
4154 return GetScrollMaxXY(aScrollMaxX
, nsnull
);
4158 nsGlobalWindow::GetScrollMaxY(PRInt32
* aScrollMaxY
)
4160 NS_ENSURE_ARG_POINTER(aScrollMaxY
);
4162 return GetScrollMaxXY(nsnull
, aScrollMaxY
);
4166 nsGlobalWindow::GetScrollXY(PRInt32
* aScrollX
, PRInt32
* aScrollY
,
4169 FORWARD_TO_OUTER(GetScrollXY
, (aScrollX
, aScrollY
, aDoFlush
),
4170 NS_ERROR_NOT_INITIALIZED
);
4173 FlushPendingNotifications(Flush_Layout
);
4175 EnsureSizeUpToDate();
4178 nsIScrollableFrame
*sf
= GetScrollFrame();
4182 nsPoint scrollPos
= sf
->GetScrollPosition();
4183 if (scrollPos
!= nsPoint(0,0) && !aDoFlush
) {
4184 // Oh, well. This is the expensive case -- the window is scrolled and we
4185 // didn't actually flush yet. Repeat, but with a flush, since the content
4186 // may get shorter and hence our scroll position may decrease.
4187 return GetScrollXY(aScrollX
, aScrollY
, PR_TRUE
);
4191 *aScrollX
= nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.x
);
4193 *aScrollY
= nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.y
);
4199 nsGlobalWindow::GetScrollX(PRInt32
* aScrollX
)
4201 NS_ENSURE_ARG_POINTER(aScrollX
);
4203 return GetScrollXY(aScrollX
, nsnull
, PR_FALSE
);
4207 nsGlobalWindow::GetScrollY(PRInt32
* aScrollY
)
4209 NS_ENSURE_ARG_POINTER(aScrollY
);
4211 return GetScrollXY(nsnull
, aScrollY
, PR_FALSE
);
4215 nsGlobalWindow::GetLength(PRUint32
* aLength
)
4217 nsCOMPtr
<nsIDOMWindowCollection
> frames
;
4218 if (NS_SUCCEEDED(GetFrames(getter_AddRefs(frames
))) && frames
) {
4219 return frames
->GetLength(aLength
);
4221 return NS_ERROR_FAILURE
;
4225 nsGlobalWindow::DispatchCustomEvent(const char *aEventName
)
4227 PRBool defaultActionEnabled
= PR_TRUE
;
4228 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
4229 nsContentUtils::DispatchTrustedEvent(doc
,
4230 static_cast<nsIScriptGlobalObject
*>(this),
4231 NS_ConvertASCIItoUTF16(aEventName
),
4232 PR_TRUE
, PR_TRUE
, &defaultActionEnabled
);
4234 return defaultActionEnabled
;
4237 static already_AddRefed
<nsIDocShellTreeItem
>
4238 GetCallerDocShellTreeItem()
4240 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
4241 nsIDocShellTreeItem
*callerItem
= nsnull
;
4244 nsCOMPtr
<nsIWebNavigation
> callerWebNav
=
4245 do_GetInterface(nsJSUtils::GetDynamicScriptGlobal(cx
));
4248 CallQueryInterface(callerWebNav
, &callerItem
);
4256 nsGlobalWindow::WindowExists(const nsAString
& aName
,
4257 PRBool aLookForCallerOnJSStack
)
4259 NS_PRECONDITION(IsOuterWindow(), "Must be outer window");
4260 NS_PRECONDITION(mDocShell
, "Must have docshell");
4262 nsCOMPtr
<nsIDocShellTreeItem
> caller
;
4263 if (aLookForCallerOnJSStack
) {
4264 caller
= GetCallerDocShellTreeItem();
4267 nsCOMPtr
<nsIDocShellTreeItem
> docShell
= do_QueryInterface(mDocShell
);
4268 NS_ASSERTION(docShell
,
4269 "Docshell doesn't implement nsIDocShellTreeItem?");
4275 nsCOMPtr
<nsIDocShellTreeItem
> namedItem
;
4276 docShell
->FindItemWithName(PromiseFlatString(aName
).get(), nsnull
, caller
,
4277 getter_AddRefs(namedItem
));
4278 return namedItem
!= nsnull
;
4281 already_AddRefed
<nsIWidget
>
4282 nsGlobalWindow::GetMainWidget()
4284 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4285 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4287 nsIWidget
*widget
= nsnull
;
4289 if (treeOwnerAsWin
) {
4290 treeOwnerAsWin
->GetMainWidget(&widget
);
4297 nsGlobalWindow::GetNearestWidget()
4299 nsIDocShell
* docShell
= GetDocShell();
4300 NS_ENSURE_TRUE(docShell
, nsnull
);
4301 nsCOMPtr
<nsIPresShell
> presShell
;
4302 docShell
->GetPresShell(getter_AddRefs(presShell
));
4303 NS_ENSURE_TRUE(presShell
, nsnull
);
4304 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
4305 NS_ENSURE_TRUE(rootFrame
, nsnull
);
4306 return rootFrame
->GetView()->GetNearestWidget(nsnull
);
4310 nsGlobalWindow::SetFullScreen(PRBool aFullScreen
)
4312 FORWARD_TO_OUTER(SetFullScreen
, (aFullScreen
), NS_ERROR_NOT_INITIALIZED
);
4314 NS_ENSURE_TRUE(mDocShell
, NS_ERROR_FAILURE
);
4316 PRBool rootWinFullScreen
;
4317 GetFullScreen(&rootWinFullScreen
);
4318 // Only chrome can change our fullScreen mode.
4319 if (aFullScreen
== rootWinFullScreen
||
4320 !nsContentUtils::IsCallerTrustedForWrite()) {
4324 // SetFullScreen needs to be called on the root window, so get that
4325 // via the DocShell tree, and if we are not already the root,
4326 // call SetFullScreen on that window instead.
4327 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryInterface(mDocShell
);
4328 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
4329 treeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
4330 nsCOMPtr
<nsIDOMWindowInternal
> window
= do_GetInterface(rootItem
);
4332 return NS_ERROR_FAILURE
;
4333 if (rootItem
!= treeItem
)
4334 return window
->SetFullScreen(aFullScreen
);
4336 // make sure we don't try to set full screen on a non-chrome window,
4337 // which might happen in embedding world
4339 treeItem
->GetItemType(&itemType
);
4340 if (itemType
!= nsIDocShellTreeItem::typeChrome
)
4341 return NS_ERROR_FAILURE
;
4343 // If we are already in full screen mode, just return.
4344 if (mFullScreen
== aFullScreen
)
4347 // dispatch a "fullscreen" DOM event so that XUL apps can
4348 // respond visually if we are kicked into full screen mode
4349 if (!DispatchCustomEvent("fullscreen")) {
4353 // Prevent chrome documents which are still loading from resizing
4354 // the window after we set fullscreen mode.
4355 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4356 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4357 nsCOMPtr
<nsIXULWindow
> xulWin(do_GetInterface(treeOwnerAsWin
));
4358 if (aFullScreen
&& xulWin
) {
4359 xulWin
->SetIntrinsicallySized(PR_FALSE
);
4362 // Set this before so if widget sends an event indicating its
4363 // gone full screen, the state trap above works.
4364 mFullScreen
= aFullScreen
;
4366 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
4368 widget
->MakeFullScreen(aFullScreen
);
4374 nsGlobalWindow::GetFullScreen(PRBool
* aFullScreen
)
4376 FORWARD_TO_OUTER(GetFullScreen
, (aFullScreen
), NS_ERROR_NOT_INITIALIZED
);
4378 // Get the fullscreen value of the root window, to always have the value
4379 // accurate, even when called from content.
4380 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryInterface(mDocShell
);
4382 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
4383 treeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
4384 if (rootItem
!= treeItem
) {
4385 nsCOMPtr
<nsIDOMWindowInternal
> window
= do_GetInterface(rootItem
);
4387 return window
->GetFullScreen(aFullScreen
);
4391 // We are the root window, or something went wrong. Return our internal value.
4392 *aFullScreen
= mFullScreen
;
4397 nsGlobalWindow::DOMWindowDumpEnabled()
4399 #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
4400 // In optimized builds we check a pref that controls if we should
4401 // enable output from dump() or not, in debug builds it's always
4403 return gDOMWindowDumpEnabled
;
4410 nsGlobalWindow::Dump(const nsAString
& aStr
)
4412 if (!DOMWindowDumpEnabled()) {
4416 char *cstr
= ToNewUTF8String(aStr
);
4418 #if defined(XP_MAC) || defined(XP_MACOSX)
4419 // have to convert \r to \n so that printing to the console works
4420 char *c
= cstr
, *cEnd
= cstr
+ strlen(cstr
);
4429 FILE *fp
= gDumpFile
? gDumpFile
: stdout
;
4432 nsMemory::Free(cstr
);
4439 nsGlobalWindow::EnsureReflowFlushAndPaint()
4441 NS_ASSERTION(IsOuterWindow(), "EnsureReflowFlushAndPaint() must be called on"
4442 "the outer window");
4443 NS_ASSERTION(mDocShell
, "EnsureReflowFlushAndPaint() called with no "
4449 nsCOMPtr
<nsIPresShell
> presShell
;
4450 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
4455 // Flush pending reflows.
4457 mDoc
->FlushPendingNotifications(Flush_Layout
);
4460 // Unsuppress painting.
4461 presShell
->UnsuppressPainting();
4465 nsGlobalWindow::GetTextZoom(float *aZoom
)
4467 FORWARD_TO_OUTER(GetTextZoom
, (aZoom
), NS_ERROR_NOT_INITIALIZED
);
4470 nsCOMPtr
<nsIContentViewer
> contentViewer
;
4471 mDocShell
->GetContentViewer(getter_AddRefs(contentViewer
));
4472 nsCOMPtr
<nsIMarkupDocumentViewer
> markupViewer(do_QueryInterface(contentViewer
));
4475 return markupViewer
->GetTextZoom(aZoom
);
4478 return NS_ERROR_FAILURE
;
4482 nsGlobalWindow::SetTextZoom(float aZoom
)
4484 FORWARD_TO_OUTER(SetTextZoom
, (aZoom
), NS_ERROR_NOT_INITIALIZED
);
4487 nsCOMPtr
<nsIContentViewer
> contentViewer
;
4488 mDocShell
->GetContentViewer(getter_AddRefs(contentViewer
));
4489 nsCOMPtr
<nsIMarkupDocumentViewer
> markupViewer(do_QueryInterface(contentViewer
));
4492 return markupViewer
->SetTextZoom(aZoom
);
4494 return NS_ERROR_FAILURE
;
4499 nsGlobalWindow::MakeScriptDialogTitle(nsAString
&aOutTitle
)
4501 aOutTitle
.Truncate();
4503 // Try to get a host from the running principal -- this will do the
4504 // right thing for javascript: and data: documents.
4506 nsresult rv
= NS_OK
;
4507 NS_ASSERTION(nsContentUtils::GetSecurityManager(),
4508 "Global Window has no security manager!");
4509 if (nsContentUtils::GetSecurityManager()) {
4510 nsCOMPtr
<nsIPrincipal
> principal
;
4511 rv
= nsContentUtils::GetSecurityManager()->
4512 GetSubjectPrincipal(getter_AddRefs(principal
));
4514 if (NS_SUCCEEDED(rv
) && principal
) {
4515 nsCOMPtr
<nsIURI
> uri
;
4516 rv
= principal
->GetURI(getter_AddRefs(uri
));
4518 if (NS_SUCCEEDED(rv
) && uri
) {
4519 // remove user:pass for privacy and spoof prevention
4521 nsCOMPtr
<nsIURIFixup
> fixup(do_GetService(NS_URIFIXUP_CONTRACTID
));
4523 nsCOMPtr
<nsIURI
> fixedURI
;
4524 rv
= fixup
->CreateExposableURI(uri
, getter_AddRefs(fixedURI
));
4525 if (NS_SUCCEEDED(rv
) && fixedURI
) {
4527 fixedURI
->GetHost(host
);
4529 if (!host
.IsEmpty()) {
4530 // if this URI has a host we'll show it. For other
4531 // schemes (e.g. file:) we fall back to the localized
4534 nsCAutoString prepath
;
4535 fixedURI
->GetPrePath(prepath
);
4537 NS_ConvertUTF8toUTF16
ucsPrePath(prepath
);
4538 const PRUnichar
*formatStrings
[] = { ucsPrePath
.get() };
4539 nsXPIDLString tempString
;
4540 nsContentUtils::FormatLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
4542 formatStrings
, NS_ARRAY_LENGTH(formatStrings
),
4544 aOutTitle
= tempString
;
4550 else { // failed to get subject principal
4551 NS_WARNING("No script principal? Who is calling alert/confirm/prompt?!");
4555 if (aOutTitle
.IsEmpty()) {
4556 // We didn't find a host so use the generic heading
4557 nsXPIDLString tempString
;
4558 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
4559 "ScriptDlgGenericHeading",
4561 aOutTitle
= tempString
;
4565 if (aOutTitle
.IsEmpty()) {
4566 NS_WARNING("could not get ScriptDlgGenericHeading string from string bundle");
4567 aOutTitle
.AssignLiteral("[Script]");
4573 nsGlobalWindow::CanMoveResizeWindows()
4575 if (!CanSetProperty("dom.disable_window_move_resize"))
4578 if (gMouseDown
&& !gDragServiceDisabled
) {
4579 nsCOMPtr
<nsIDragService
> ds
=
4580 do_GetService("@mozilla.org/widget/dragservice;1");
4582 gDragServiceDisabled
= PR_TRUE
;
4590 nsGlobalWindow::Alert(const nsAString
& aString
)
4592 FORWARD_TO_OUTER(Alert
, (aString
), NS_ERROR_NOT_INITIALIZED
);
4594 if (AreDialogsBlocked())
4595 return NS_ERROR_NOT_AVAILABLE
;
4597 // We have to capture this now so as not to get confused with the
4598 // popup state we push next
4599 PRBool shouldEnableDisableDialog
= DialogOpenAttempted();
4601 // Reset popup state while opening a modal dialog, and firing events
4602 // about the dialog, to prevent the current state from being active
4603 // the whole time a modal dialog is open.
4604 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
4606 // Special handling for alert(null) in JS for backwards
4609 NS_NAMED_LITERAL_STRING(null_str
, "null");
4611 const nsAString
*str
= DOMStringIsNull(aString
) ? &null_str
: &aString
;
4613 // Before bringing up the window, unsuppress painting and flush
4615 EnsureReflowFlushAndPaint();
4618 MakeScriptDialogTitle(title
);
4620 // Remove non-terminating null characters from the
4621 // string. See bug #310037.
4623 nsContentUtils::StripNullChars(*str
, final
);
4626 nsCOMPtr
<nsIPromptFactory
> promptFac
=
4627 do_GetService("@mozilla.org/prompter;1", &rv
);
4628 NS_ENSURE_SUCCESS(rv
, rv
);
4630 nsCOMPtr
<nsIPrompt
> prompt
;
4631 rv
= promptFac
->GetPrompt(this, NS_GET_IID(nsIPrompt
),
4632 reinterpret_cast<void**>(&prompt
));
4633 NS_ENSURE_SUCCESS(rv
, rv
);
4635 nsCOMPtr
<nsIWritablePropertyBag2
> promptBag
= do_QueryInterface(prompt
);
4637 promptBag
->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), PR_TRUE
);
4639 if (shouldEnableDisableDialog
) {
4640 PRBool disallowDialog
= PR_FALSE
;
4641 nsXPIDLString label
;
4642 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
4643 "ScriptDialogLabel", label
);
4645 rv
= prompt
->AlertCheck(title
.get(), final
.get(), label
.get(),
4648 PreventFurtherDialogs();
4650 rv
= prompt
->Alert(title
.get(), final
.get());
4657 nsGlobalWindow::Confirm(const nsAString
& aString
, PRBool
* aReturn
)
4659 FORWARD_TO_OUTER(Confirm
, (aString
, aReturn
), NS_ERROR_NOT_INITIALIZED
);
4661 if (AreDialogsBlocked())
4662 return NS_ERROR_NOT_AVAILABLE
;
4664 // We have to capture this now so as not to get confused with the popup state
4666 PRBool shouldEnableDisableDialog
= DialogOpenAttempted();
4668 // Reset popup state while opening a modal dialog, and firing events
4669 // about the dialog, to prevent the current state from being active
4670 // the whole time a modal dialog is open.
4671 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
4673 *aReturn
= PR_FALSE
;
4675 // Before bringing up the window, unsuppress painting and flush
4677 EnsureReflowFlushAndPaint();
4680 MakeScriptDialogTitle(title
);
4682 // Remove non-terminating null characters from the
4683 // string. See bug #310037.
4685 nsContentUtils::StripNullChars(aString
, final
);
4688 nsCOMPtr
<nsIPromptFactory
> promptFac
=
4689 do_GetService("@mozilla.org/prompter;1", &rv
);
4690 NS_ENSURE_SUCCESS(rv
, rv
);
4692 nsCOMPtr
<nsIPrompt
> prompt
;
4693 rv
= promptFac
->GetPrompt(this, NS_GET_IID(nsIPrompt
),
4694 reinterpret_cast<void**>(&prompt
));
4695 NS_ENSURE_SUCCESS(rv
, rv
);
4697 nsCOMPtr
<nsIWritablePropertyBag2
> promptBag
= do_QueryInterface(prompt
);
4699 promptBag
->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), PR_TRUE
);
4701 if (shouldEnableDisableDialog
) {
4702 PRBool disallowDialog
= PR_FALSE
;
4703 nsXPIDLString label
;
4704 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
4705 "ScriptDialogLabel", label
);
4707 rv
= prompt
->ConfirmCheck(title
.get(), final
.get(), label
.get(),
4708 &disallowDialog
, aReturn
);
4710 PreventFurtherDialogs();
4712 rv
= prompt
->Confirm(title
.get(), final
.get(), aReturn
);
4719 nsGlobalWindow::Prompt(const nsAString
& aMessage
, const nsAString
& aInitial
,
4722 FORWARD_TO_OUTER(Prompt
, (aMessage
, aInitial
, aReturn
),
4723 NS_ERROR_NOT_INITIALIZED
);
4725 SetDOMStringToNull(aReturn
);
4727 if (AreDialogsBlocked())
4728 return NS_ERROR_NOT_AVAILABLE
;
4730 // We have to capture this now so as not to get confused with the popup state
4732 PRBool shouldEnableDisableDialog
= DialogOpenAttempted();
4734 // Reset popup state while opening a modal dialog, and firing events
4735 // about the dialog, to prevent the current state from being active
4736 // the whole time a modal dialog is open.
4737 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
4739 // Before bringing up the window, unsuppress painting and flush
4741 EnsureReflowFlushAndPaint();
4744 MakeScriptDialogTitle(title
);
4746 // Remove non-terminating null characters from the
4747 // string. See bug #310037.
4748 nsAutoString fixedMessage
, fixedInitial
;
4749 nsContentUtils::StripNullChars(aMessage
, fixedMessage
);
4750 nsContentUtils::StripNullChars(aInitial
, fixedInitial
);
4753 nsCOMPtr
<nsIPromptFactory
> promptFac
=
4754 do_GetService("@mozilla.org/prompter;1", &rv
);
4755 NS_ENSURE_SUCCESS(rv
, rv
);
4757 nsCOMPtr
<nsIPrompt
> prompt
;
4758 rv
= promptFac
->GetPrompt(this, NS_GET_IID(nsIPrompt
),
4759 reinterpret_cast<void**>(&prompt
));
4760 NS_ENSURE_SUCCESS(rv
, rv
);
4762 nsCOMPtr
<nsIWritablePropertyBag2
> promptBag
= do_QueryInterface(prompt
);
4764 promptBag
->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), PR_TRUE
);
4766 // Pass in the default value, if any.
4767 PRUnichar
*inoutValue
= ToNewUnicode(fixedInitial
);
4768 PRBool disallowDialog
= PR_FALSE
;
4770 nsXPIDLString label
;
4771 if (shouldEnableDisableDialog
) {
4772 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
4773 "ScriptDialogLabel", label
);
4777 rv
= prompt
->Prompt(title
.get(), fixedMessage
.get(),
4778 &inoutValue
, label
.get(), &disallowDialog
, &ok
);
4780 if (disallowDialog
) {
4781 PreventFurtherDialogs();
4784 NS_ENSURE_SUCCESS(rv
, rv
);
4786 nsAdoptingString
outValue(inoutValue
);
4788 if (ok
&& outValue
) {
4789 aReturn
.Assign(outValue
);
4796 nsGlobalWindow::Focus()
4798 FORWARD_TO_OUTER(Focus
, (), NS_ERROR_NOT_INITIALIZED
);
4800 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
4804 nsCOMPtr
<nsIBaseWindow
> baseWin
= do_QueryInterface(mDocShell
);
4806 PRBool isVisible
= PR_FALSE
;
4808 baseWin
->GetVisibility(&isVisible
);
4812 // A hidden tab is being focused, ignore this call.
4816 nsIDOMWindowInternal
*caller
=
4817 static_cast<nsIDOMWindowInternal
*>(nsContentUtils::GetWindowFromCaller());
4818 nsCOMPtr
<nsIDOMWindowInternal
> opener
;
4819 GetOpener(getter_AddRefs(opener
));
4821 // Enforce dom.disable_window_flip (for non-chrome), but still allow the
4822 // window which opened us to raise us at times when popups are allowed
4823 // (bugs 355482 and 369306).
4824 PRBool canFocus
= CanSetProperty("dom.disable_window_flip") ||
4825 (opener
== caller
&&
4826 RevisePopupAbuseLevel(gPopupControlState
) < openAbused
);
4828 nsCOMPtr
<nsIDOMWindow
> activeWindow
;
4829 fm
->GetActiveWindow(getter_AddRefs(activeWindow
));
4831 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryInterface(mDocShell
);
4832 NS_ASSERTION(treeItem
, "What happened?");
4833 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
4834 treeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
4835 nsCOMPtr
<nsIDOMWindow
> rootWin
= do_GetInterface(rootItem
);
4836 PRBool isActive
= (rootWin
== activeWindow
);
4838 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4839 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4840 if (treeOwnerAsWin
&& (canFocus
|| isActive
)) {
4841 PRBool isEnabled
= PR_TRUE
;
4842 if (NS_SUCCEEDED(treeOwnerAsWin
->GetEnabled(&isEnabled
)) && !isEnabled
) {
4843 NS_WARNING( "Should not try to set the focus on a disabled window" );
4847 // XXXndeakin not sure what this is for or if it should go somewhere else
4848 nsCOMPtr
<nsIEmbeddingSiteWindow
> embeddingWin(do_GetInterface(treeOwnerAsWin
));
4850 embeddingWin
->SetFocus();
4856 nsCOMPtr
<nsIPresShell
> presShell
;
4857 // Don't look for a presshell if we're a root chrome window that's got
4858 // about:blank loaded. We don't want to focus our widget in that case.
4859 // XXXbz should we really be checking for IsInitialDocument() instead?
4860 PRBool lookForPresShell
= PR_TRUE
;
4861 PRInt32 itemType
= nsIDocShellTreeItem::typeContent
;
4862 treeItem
->GetItemType(&itemType
);
4863 if (itemType
== nsIDocShellTreeItem::typeChrome
&&
4864 GetPrivateRoot() == static_cast<nsIDOMWindowInternal
*>(this) &&
4866 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
4867 NS_ASSERTION(doc
, "Bogus doc?");
4868 nsIURI
* ourURI
= doc
->GetDocumentURI();
4870 lookForPresShell
= !IsAboutBlank(ourURI
);
4874 if (lookForPresShell
) {
4875 mDocShell
->GetEldestPresShell(getter_AddRefs(presShell
));
4878 nsCOMPtr
<nsIDocShellTreeItem
> parentDsti
;
4879 treeItem
->GetParent(getter_AddRefs(parentDsti
));
4881 // set the parent's current focus to the frame containing this window.
4882 nsCOMPtr
<nsIDOMWindow
> parent(do_GetInterface(parentDsti
));
4884 nsCOMPtr
<nsIDOMDocument
> parentdomdoc
;
4885 parent
->GetDocument(getter_AddRefs(parentdomdoc
));
4887 nsCOMPtr
<nsIDocument
> parentdoc
= do_QueryInterface(parentdomdoc
);
4891 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(mDocument
);
4892 nsIContent
* frame
= parentdoc
->FindContentForSubDocument(doc
);
4893 nsCOMPtr
<nsIDOMElement
> frameElement
= do_QueryInterface(frame
);
4895 PRUint32 flags
= nsIFocusManager::FLAG_NOSCROLL
;
4897 flags
|= nsIFocusManager::FLAG_RAISE
;
4898 return fm
->SetFocus(frameElement
, flags
);
4901 else if (canFocus
) {
4902 // if there is no parent, this must be a toplevel window, so raise the
4903 // window if canFocus is true
4904 return fm
->SetActiveWindow(this);
4911 nsGlobalWindow::Blur()
4913 FORWARD_TO_OUTER(Blur
, (), NS_ERROR_NOT_INITIALIZED
);
4915 // If dom.disable_window_flip == true, then content should not be allowed
4916 // to call this function (this would allow popunders, bug 369306)
4917 if (!CanSetProperty("dom.disable_window_flip")) {
4921 // If embedding apps don't implement nsIEmbeddingSiteWindow2, we
4922 // shouldn't throw exceptions to web content.
4923 nsresult rv
= NS_OK
;
4925 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
4926 GetTreeOwner(getter_AddRefs(treeOwner
));
4927 nsCOMPtr
<nsIEmbeddingSiteWindow2
> siteWindow(do_GetInterface(treeOwner
));
4929 // This method call may cause mDocShell to become nsnull.
4930 rv
= siteWindow
->Blur();
4932 // if the root is focused, clear the focus
4933 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
4934 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(mDocument
);
4935 if (fm
&& mDocument
) {
4936 nsCOMPtr
<nsIDOMElement
> element
;
4937 fm
->GetFocusedElementForWindow(this, PR_FALSE
, nsnull
, getter_AddRefs(element
));
4938 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(element
);
4939 if (content
== doc
->GetRootElement())
4940 fm
->ClearFocus(this);
4948 nsGlobalWindow::Back()
4950 FORWARD_TO_OUTER(Back
, (), NS_ERROR_NOT_INITIALIZED
);
4952 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
4953 NS_ENSURE_TRUE(webNav
, NS_ERROR_FAILURE
);
4955 return webNav
->GoBack();
4959 nsGlobalWindow::Forward()
4961 FORWARD_TO_OUTER(Forward
, (), NS_ERROR_NOT_INITIALIZED
);
4963 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
4964 NS_ENSURE_TRUE(webNav
, NS_ERROR_FAILURE
);
4966 return webNav
->GoForward();
4970 nsGlobalWindow::Home()
4972 FORWARD_TO_OUTER(Home
, (), NS_ERROR_NOT_INITIALIZED
);
4977 nsAdoptingString homeURL
=
4978 nsContentUtils::GetLocalizedStringPref(PREF_BROWSER_STARTUP_HOMEPAGE
);
4980 if (homeURL
.IsEmpty()) {
4981 // if all else fails, use this
4983 printf("all else failed. using %s as the home page\n", DEFAULT_HOME_PAGE
);
4985 CopyASCIItoUTF16(DEFAULT_HOME_PAGE
, homeURL
);
4990 // Firefox lets the user specify multiple home pages to open in
4991 // individual tabs by separating them with '|'. Since we don't
4992 // have the machinery in place to easily open new tabs from here,
4993 // simply truncate the homeURL at the first '|' character to
4994 // prevent any possibilities of leaking the users list of home
4995 // pages to the first home page.
4997 // Once bug https://bugzilla.mozilla.org/show_bug.cgi?id=221445 is
4998 // fixed we can revisit this.
4999 PRInt32 firstPipe
= homeURL
.FindChar('|');
5001 if (firstPipe
> 0) {
5002 homeURL
.Truncate(firstPipe
);
5008 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
5009 NS_ENSURE_TRUE(webNav
, NS_ERROR_FAILURE
);
5010 rv
= webNav
->LoadURI(homeURL
.get(),
5011 nsIWebNavigation::LOAD_FLAGS_NONE
,
5015 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
5020 nsGlobalWindow::Stop()
5022 FORWARD_TO_OUTER(Stop
, (), NS_ERROR_NOT_INITIALIZED
);
5024 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
5028 return webNav
->Stop(nsIWebNavigation::STOP_ALL
);
5032 nsGlobalWindow::Print()
5035 FORWARD_TO_OUTER(Print
, (), NS_ERROR_NOT_INITIALIZED
);
5037 if (AreDialogsBlocked() || !ConfirmDialogAllowed())
5038 return NS_ERROR_NOT_AVAILABLE
;
5040 nsCOMPtr
<nsIWebBrowserPrint
> webBrowserPrint
;
5041 if (NS_SUCCEEDED(GetInterface(NS_GET_IID(nsIWebBrowserPrint
),
5042 getter_AddRefs(webBrowserPrint
)))) {
5044 nsCOMPtr
<nsIPrintSettingsService
> printSettingsService
=
5045 do_GetService("@mozilla.org/gfx/printsettings-service;1");
5047 nsCOMPtr
<nsIPrintSettings
> printSettings
;
5048 if (printSettingsService
) {
5049 PRBool printSettingsAreGlobal
=
5050 nsContentUtils::GetBoolPref("print.use_global_printsettings", PR_FALSE
);
5052 if (printSettingsAreGlobal
) {
5053 printSettingsService
->GetGlobalPrintSettings(getter_AddRefs(printSettings
));
5055 nsXPIDLString printerName
;
5056 printSettings
->GetPrinterName(getter_Copies(printerName
));
5057 if (printerName
.IsEmpty()) {
5058 printSettingsService
->GetDefaultPrinterName(getter_Copies(printerName
));
5059 printSettings
->SetPrinterName(printerName
);
5061 printSettingsService
->InitPrintSettingsFromPrinter(printerName
, printSettings
);
5062 printSettingsService
->InitPrintSettingsFromPrefs(printSettings
,
5064 nsIPrintSettings::kInitSaveAll
);
5066 printSettingsService
->GetNewPrintSettings(getter_AddRefs(printSettings
));
5070 webBrowserPrint
->Print(printSettings
, nsnull
);
5071 LeaveModalState(nsnull
);
5073 PRBool savePrintSettings
=
5074 nsContentUtils::GetBoolPref("print.save_print_settings", PR_FALSE
);
5075 if (printSettingsAreGlobal
&& savePrintSettings
) {
5076 printSettingsService
->
5077 SavePrintSettingsToPrefs(printSettings
,
5079 nsIPrintSettings::kInitSaveAll
);
5080 printSettingsService
->
5081 SavePrintSettingsToPrefs(printSettings
,
5083 nsIPrintSettings::kInitSavePrinterName
);
5086 webBrowserPrint
->GetGlobalPrintSettings(getter_AddRefs(printSettings
));
5087 webBrowserPrint
->Print(printSettings
, nsnull
);
5090 #endif //NS_PRINTING
5096 nsGlobalWindow::MoveTo(PRInt32 aXPos
, PRInt32 aYPos
)
5098 FORWARD_TO_OUTER(MoveTo
, (aXPos
, aYPos
), NS_ERROR_NOT_INITIALIZED
);
5101 * If caller is not chrome and the user has not explicitly exempted the site,
5102 * prevent window.moveTo() by exiting early
5105 if (!CanMoveResizeWindows() || IsFrame()) {
5109 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
5110 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
5111 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
5113 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&aXPos
, &aYPos
),
5116 // mild abuse of a "size" object so we don't need more helper functions
5117 nsIntSize
devPos(CSSToDevIntPixels(nsIntSize(aXPos
, aYPos
)));
5119 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(devPos
.width
, devPos
.height
),
5126 nsGlobalWindow::MoveBy(PRInt32 aXDif
, PRInt32 aYDif
)
5128 FORWARD_TO_OUTER(MoveBy
, (aXDif
, aYDif
), NS_ERROR_NOT_INITIALIZED
);
5131 * If caller is not chrome and the user has not explicitly exempted the site,
5132 * prevent window.moveBy() by exiting early
5135 if (!CanMoveResizeWindows() || IsFrame()) {
5139 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
5140 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
5141 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
5143 // To do this correctly we have to convert what we get from GetPosition
5144 // into CSS pixels, add the arguments, do the security check, and
5145 // then convert back to device pixels for the call to SetPosition.
5148 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
), NS_ERROR_FAILURE
);
5150 // mild abuse of a "size" object so we don't need more helper functions
5151 nsIntSize
cssPos(DevToCSSIntPixels(nsIntSize(x
, y
)));
5153 cssPos
.width
+= aXDif
;
5154 cssPos
.height
+= aYDif
;
5156 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&cssPos
.width
,
5160 nsIntSize
newDevPos(CSSToDevIntPixels(cssPos
));
5162 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(newDevPos
.width
,
5170 nsGlobalWindow::ResizeTo(PRInt32 aWidth
, PRInt32 aHeight
)
5172 FORWARD_TO_OUTER(ResizeTo
, (aWidth
, aHeight
), NS_ERROR_NOT_INITIALIZED
);
5175 * If caller is not chrome and the user has not explicitly exempted the site,
5176 * prevent window.resizeTo() by exiting early
5179 if (!CanMoveResizeWindows() || IsFrame()) {
5183 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
5184 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
5185 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
5187 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&aWidth
, &aHeight
),
5190 nsIntSize
devSz(CSSToDevIntPixels(nsIntSize(aWidth
, aHeight
)));
5192 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetSize(devSz
.width
, devSz
.height
, PR_TRUE
),
5199 nsGlobalWindow::ResizeBy(PRInt32 aWidthDif
, PRInt32 aHeightDif
)
5201 FORWARD_TO_OUTER(ResizeBy
, (aWidthDif
, aHeightDif
), NS_ERROR_NOT_INITIALIZED
);
5204 * If caller is not chrome and the user has not explicitly exempted the site,
5205 * prevent window.resizeBy() by exiting early
5208 if (!CanMoveResizeWindows() || IsFrame()) {
5212 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
5213 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
5214 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
5216 PRInt32 width
, height
;
5217 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetSize(&width
, &height
), NS_ERROR_FAILURE
);
5219 // To do this correctly we have to convert what we got from GetSize
5220 // into CSS pixels, add the arguments, do the security check, and
5221 // then convert back to device pixels for the call to SetSize.
5223 nsIntSize
cssSize(DevToCSSIntPixels(nsIntSize(width
, height
)));
5225 cssSize
.width
+= aWidthDif
;
5226 cssSize
.height
+= aHeightDif
;
5228 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&cssSize
.width
,
5232 nsIntSize
newDevSize(CSSToDevIntPixels(cssSize
));
5234 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetSize(newDevSize
.width
,
5243 nsGlobalWindow::SizeToContent()
5245 FORWARD_TO_OUTER(SizeToContent
, (), NS_ERROR_NOT_INITIALIZED
);
5252 * If caller is not chrome and the user has not explicitly exempted the site,
5253 * prevent window.sizeToContent() by exiting early
5256 if (!CanMoveResizeWindows() || IsFrame()) {
5260 // The content viewer does a check to make sure that it's a content
5261 // viewer for a toplevel docshell.
5263 nsCOMPtr
<nsIContentViewer
> cv
;
5264 mDocShell
->GetContentViewer(getter_AddRefs(cv
));
5265 nsCOMPtr
<nsIMarkupDocumentViewer
> markupViewer(do_QueryInterface(cv
));
5266 NS_ENSURE_TRUE(markupViewer
, NS_ERROR_FAILURE
);
5267 NS_ENSURE_SUCCESS(markupViewer
->SizeToContent(), NS_ERROR_FAILURE
);
5273 nsGlobalWindow::GetWindowRoot(nsIDOMEventTarget
**aWindowRoot
)
5275 nsCOMPtr
<nsPIWindowRoot
> root
= GetTopWindowRoot();
5276 return CallQueryInterface(root
, aWindowRoot
);
5279 already_AddRefed
<nsPIWindowRoot
>
5280 nsGlobalWindow::GetTopWindowRoot()
5282 nsIDOMWindowInternal
*rootWindow
= GetPrivateRoot();
5283 nsCOMPtr
<nsPIDOMWindow
> piWin(do_QueryInterface(rootWindow
));
5287 nsCOMPtr
<nsPIWindowRoot
> window
= do_QueryInterface(piWin
->GetChromeEventHandler());
5288 return window
.forget();
5292 nsGlobalWindow::Scroll(PRInt32 aXScroll
, PRInt32 aYScroll
)
5294 return ScrollTo(aXScroll
, aYScroll
);
5298 nsGlobalWindow::ScrollTo(PRInt32 aXScroll
, PRInt32 aYScroll
)
5300 FlushPendingNotifications(Flush_Layout
);
5301 nsIScrollableFrame
*sf
= GetScrollFrame();
5304 // Here we calculate what the max pixel value is that we can
5305 // scroll to, we do this by dividing maxint with the pixel to
5306 // twips conversion factor, and substracting 4, the 4 comes from
5307 // experimenting with this value, anything less makes the view
5308 // code not scroll correctly, I have no idea why. -- jst
5309 const PRInt32 maxpx
= nsPresContext::AppUnitsToIntCSSPixels(0x7fffffff) - 4;
5311 if (aXScroll
> maxpx
) {
5315 if (aYScroll
> maxpx
) {
5318 sf
->ScrollTo(nsPoint(nsPresContext::CSSPixelsToAppUnits(aXScroll
),
5319 nsPresContext::CSSPixelsToAppUnits(aYScroll
)),
5320 nsIScrollableFrame::INSTANT
);
5327 nsGlobalWindow::ScrollBy(PRInt32 aXScrollDif
, PRInt32 aYScrollDif
)
5329 FlushPendingNotifications(Flush_Layout
);
5330 nsIScrollableFrame
*sf
= GetScrollFrame();
5333 nsPoint scrollPos
= sf
->GetScrollPosition();
5334 // It seems like it would make more sense for ScrollBy to use
5335 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
5336 // Perhaps Web content does too.
5337 return ScrollTo(nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.x
) + aXScrollDif
,
5338 nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.y
) + aYScrollDif
);
5345 nsGlobalWindow::ScrollByLines(PRInt32 numLines
)
5347 FlushPendingNotifications(Flush_Layout
);
5348 nsIScrollableFrame
*sf
= GetScrollFrame();
5350 // It seems like it would make more sense for ScrollByLines to use
5351 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
5352 // Perhaps Web content does too.
5353 sf
->ScrollBy(nsIntPoint(0, numLines
), nsIScrollableFrame::LINES
,
5354 nsIScrollableFrame::INSTANT
);
5361 nsGlobalWindow::ScrollByPages(PRInt32 numPages
)
5363 FlushPendingNotifications(Flush_Layout
);
5364 nsIScrollableFrame
*sf
= GetScrollFrame();
5366 // It seems like it would make more sense for ScrollByPages to use
5367 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
5368 // Perhaps Web content does too.
5369 sf
->ScrollBy(nsIntPoint(0, numPages
), nsIScrollableFrame::PAGES
,
5370 nsIScrollableFrame::INSTANT
);
5377 nsGlobalWindow::ClearTimeout()
5379 return ClearTimeoutOrInterval();
5383 nsGlobalWindow::ClearInterval()
5385 return ClearTimeoutOrInterval();
5389 nsGlobalWindow::SetTimeout(PRInt32
*_retval
)
5391 return SetTimeoutOrInterval(PR_FALSE
, _retval
);
5395 nsGlobalWindow::SetInterval(PRInt32
*_retval
)
5397 return SetTimeoutOrInterval(PR_TRUE
, _retval
);
5401 nsGlobalWindow::SetResizable(PRBool aResizable
)
5409 ReportUseOfDeprecatedMethod(nsGlobalWindow
* aWindow
, const char* aWarning
)
5411 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(aWindow
->GetExtantDocument());
5412 nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES
,
5416 EmptyString(), 0, 0,
5417 nsIScriptError::warningFlag
,
5422 nsGlobalWindow::CaptureEvents(PRInt32 aEventFlags
)
5424 ReportUseOfDeprecatedMethod(this, "UseOfCaptureEventsWarning");
5429 nsGlobalWindow::ReleaseEvents(PRInt32 aEventFlags
)
5431 ReportUseOfDeprecatedMethod(this, "UseOfReleaseEventsWarning");
5436 nsGlobalWindow::RouteEvent(nsIDOMEvent
* aEvt
)
5438 ReportUseOfDeprecatedMethod(this, "UseOfRouteEventWarning");
5443 nsGlobalWindow::EnableExternalCapture()
5445 return NS_ERROR_FAILURE
;
5449 nsGlobalWindow::DisableExternalCapture()
5451 return NS_ERROR_FAILURE
;
5455 PRBool
IsPopupBlocked(nsIDOMDocument
* aDoc
)
5457 nsCOMPtr
<nsIPopupWindowManager
> pm
=
5458 do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID
);
5464 PRBool blocked
= PR_TRUE
;
5465 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(aDoc
));
5468 PRUint32 permission
= nsIPopupWindowManager::ALLOW_POPUP
;
5469 pm
->TestPermission(doc
->GetDocumentURI(), &permission
);
5470 blocked
= (permission
== nsIPopupWindowManager::DENY_POPUP
);
5477 nsGlobalWindow::FirePopupBlockedEvent(nsIDOMDocument
* aDoc
,
5478 nsIDOMWindow
*aRequestingWindow
, nsIURI
*aPopupURI
,
5479 const nsAString
&aPopupWindowName
,
5480 const nsAString
&aPopupWindowFeatures
)
5483 // Fire a "DOMPopupBlocked" event so that the UI can hear about
5485 nsCOMPtr
<nsIDOMDocumentEvent
> docEvent(do_QueryInterface(aDoc
));
5486 nsCOMPtr
<nsIDOMEvent
> event
;
5487 docEvent
->CreateEvent(NS_LITERAL_STRING("PopupBlockedEvents"),
5488 getter_AddRefs(event
));
5490 nsCOMPtr
<nsIDOMPopupBlockedEvent
> pbev(do_QueryInterface(event
));
5491 pbev
->InitPopupBlockedEvent(NS_LITERAL_STRING("DOMPopupBlocked"),
5492 PR_TRUE
, PR_TRUE
, aRequestingWindow
,
5493 aPopupURI
, aPopupWindowName
,
5494 aPopupWindowFeatures
);
5495 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(event
));
5496 privateEvent
->SetTrusted(PR_TRUE
);
5498 nsCOMPtr
<nsIDOMEventTarget
> targ(do_QueryInterface(aDoc
));
5499 PRBool defaultActionEnabled
;
5500 targ
->DispatchEvent(event
, &defaultActionEnabled
);
5505 void FirePopupWindowEvent(nsIDOMDocument
* aDoc
)
5507 // Fire a "PopupWindow" event
5508 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(aDoc
));
5509 nsContentUtils::DispatchTrustedEvent(doc
, aDoc
,
5510 NS_LITERAL_STRING("PopupWindow"),
5516 nsGlobalWindow::CanSetProperty(const char *aPrefName
)
5518 // Chrome can set any property.
5519 if (nsContentUtils::IsCallerTrustedForWrite()) {
5523 // If the pref is set to true, we can not set the property
5525 return !nsContentUtils::GetBoolPref(aPrefName
, PR_TRUE
);
5529 nsGlobalWindow::PopupWhitelisted()
5531 if (!IsPopupBlocked(mDocument
))
5534 nsCOMPtr
<nsIDOMWindow
> parent
;
5536 if (NS_FAILED(GetParent(getter_AddRefs(parent
))) ||
5537 parent
== static_cast<nsIDOMWindow
*>(this))
5542 return static_cast<nsGlobalWindow
*>
5543 (static_cast<nsIDOMWindow
*>
5544 (parent
.get()))->PopupWhitelisted();
5548 * Examine the current document state to see if we're in a way that is
5549 * typically abused by web designers. The window.open code uses this
5550 * routine to determine whether to allow the new window.
5551 * Returns a value from the PopupControlState enum.
5554 nsGlobalWindow::RevisePopupAbuseLevel(PopupControlState aControl
)
5556 FORWARD_TO_OUTER(RevisePopupAbuseLevel
, (aControl
), aControl
);
5558 NS_ASSERTION(mDocShell
, "Must have docshell");
5560 nsCOMPtr
<nsIDocShellTreeItem
> item(do_QueryInterface(mDocShell
));
5562 NS_ASSERTION(item
, "Docshell doesn't implement nsIDocShellTreeItem?");
5564 PRInt32 type
= nsIDocShellTreeItem::typeChrome
;
5565 item
->GetItemType(&type
);
5566 if (type
!= nsIDocShellTreeItem::typeContent
)
5569 PopupControlState abuse
= aControl
;
5571 case openControlled
:
5573 case openOverridden
:
5574 if (PopupWhitelisted())
5575 abuse
= PopupControlState(abuse
- 1);
5576 case openAllowed
: break;
5578 NS_WARNING("Strange PopupControlState!");
5581 // limit the number of simultaneously open popups
5582 if (abuse
== openAbused
|| abuse
== openControlled
) {
5583 PRInt32 popupMax
= nsContentUtils::GetIntPref("dom.popup_maximum", -1);
5584 if (popupMax
>= 0 && gOpenPopupSpamCount
>= popupMax
)
5585 abuse
= openOverridden
;
5591 /* If a window open is blocked, fire the appropriate DOM events.
5592 aBlocked signifies we just blocked a popup.
5593 aWindow signifies we just opened what is probably a popup.
5596 nsGlobalWindow::FireAbuseEvents(PRBool aBlocked
, PRBool aWindow
,
5597 const nsAString
&aPopupURL
,
5598 const nsAString
&aPopupWindowName
,
5599 const nsAString
&aPopupWindowFeatures
)
5601 // fetch the URI of the window requesting the opened window
5603 nsCOMPtr
<nsIDOMWindow
> topWindow
;
5604 GetTop(getter_AddRefs(topWindow
));
5608 nsCOMPtr
<nsIDOMDocument
> topDoc
;
5609 topWindow
->GetDocument(getter_AddRefs(topDoc
));
5611 nsCOMPtr
<nsIURI
> popupURI
;
5613 // build the URI of the would-have-been popup window
5614 // (see nsWindowWatcher::URIfromURL)
5616 // first, fetch the opener's base URI
5618 nsIURI
*baseURL
= 0;
5620 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
5621 nsCOMPtr
<nsIDOMWindow
> contextWindow
;
5624 nsIScriptContext
*currentCX
= nsJSUtils::GetDynamicScriptContext(cx
);
5626 contextWindow
= do_QueryInterface(currentCX
->GetGlobalObject());
5630 contextWindow
= static_cast<nsIDOMWindow
*>(this);
5632 nsCOMPtr
<nsIDOMDocument
> domdoc
;
5633 contextWindow
->GetDocument(getter_AddRefs(domdoc
));
5634 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(domdoc
));
5636 baseURL
= doc
->GetDocBaseURI();
5638 // use the base URI to build what would have been the popup's URI
5639 nsCOMPtr
<nsIIOService
> ios(do_GetService(NS_IOSERVICE_CONTRACTID
));
5641 ios
->NewURI(NS_ConvertUTF16toUTF8(aPopupURL
), 0, baseURL
,
5642 getter_AddRefs(popupURI
));
5644 // fire an event chock full of informative URIs
5646 FirePopupBlockedEvent(topDoc
, this, popupURI
, aPopupWindowName
,
5647 aPopupWindowFeatures
);
5649 FirePopupWindowEvent(topDoc
);
5653 nsGlobalWindow::Open(const nsAString
& aUrl
, const nsAString
& aName
,
5654 const nsAString
& aOptions
, nsIDOMWindow
**_retval
)
5656 return OpenInternal(aUrl
, aName
, aOptions
,
5657 PR_FALSE
, // aDialog
5658 PR_FALSE
, // aContentModal
5659 PR_TRUE
, // aCalledNoScript
5660 PR_FALSE
, // aDoJSFixups
5661 nsnull
, nsnull
, // No args
5662 GetPrincipal(), // aCalleePrincipal
5663 nsnull
, // aJSCallerContext
5668 nsGlobalWindow::OpenJS(const nsAString
& aUrl
, const nsAString
& aName
,
5669 const nsAString
& aOptions
, nsIDOMWindow
**_retval
)
5671 return OpenInternal(aUrl
, aName
, aOptions
,
5672 PR_FALSE
, // aDialog
5673 PR_FALSE
, // aContentModal
5674 PR_FALSE
, // aCalledNoScript
5675 PR_TRUE
, // aDoJSFixups
5676 nsnull
, nsnull
, // No args
5677 GetPrincipal(), // aCalleePrincipal
5678 nsContentUtils::GetCurrentJSContext(), // aJSCallerContext
5682 // like Open, but attaches to the new window any extra parameters past
5683 // [features] as a JS property named "arguments"
5685 nsGlobalWindow::OpenDialog(const nsAString
& aUrl
, const nsAString
& aName
,
5686 const nsAString
& aOptions
,
5687 nsISupports
* aExtraArgument
, nsIDOMWindow
** _retval
)
5689 return OpenInternal(aUrl
, aName
, aOptions
,
5691 PR_FALSE
, // aContentModal
5692 PR_TRUE
, // aCalledNoScript
5693 PR_FALSE
, // aDoJSFixups
5694 nsnull
, aExtraArgument
, // Arguments
5695 GetPrincipal(), // aCalleePrincipal
5696 nsnull
, // aJSCallerContext
5701 nsGlobalWindow::OpenDialog(const nsAString
& aUrl
, const nsAString
& aName
,
5702 const nsAString
& aOptions
, nsIDOMWindow
** _retval
)
5704 if (!nsContentUtils::IsCallerTrustedForWrite()) {
5705 return NS_ERROR_DOM_SECURITY_ERR
;
5708 nsAXPCNativeCallContext
*ncc
= nsnull
;
5709 nsresult rv
= nsContentUtils::XPConnect()->
5710 GetCurrentNativeCallContext(&ncc
);
5711 NS_ENSURE_SUCCESS(rv
, rv
);
5714 return NS_ERROR_NOT_AVAILABLE
;
5716 JSContext
*cx
= nsnull
;
5718 rv
= ncc
->GetJSContext(&cx
);
5719 NS_ENSURE_SUCCESS(rv
, rv
);
5722 jsval
*argv
= nsnull
;
5724 // XXX - need to get this as nsISupports?
5725 ncc
->GetArgc(&argc
);
5726 ncc
->GetArgvPtr(&argv
);
5728 // Strip the url, name and options from the args seen by scripts.
5729 PRUint32 argOffset
= argc
< 3 ? argc
: 3;
5730 nsCOMPtr
<nsIArray
> argvArray
;
5731 rv
= NS_CreateJSArgv(cx
, argc
- argOffset
, argv
+ argOffset
,
5732 getter_AddRefs(argvArray
));
5733 NS_ENSURE_SUCCESS(rv
, rv
);
5735 return OpenInternal(aUrl
, aName
, aOptions
,
5737 PR_FALSE
, // aContentModal
5738 PR_FALSE
, // aCalledNoScript
5739 PR_FALSE
, // aDoJSFixups
5740 argvArray
, nsnull
, // Arguments
5741 GetPrincipal(), // aCalleePrincipal
5742 cx
, // aJSCallerContext
5747 nsGlobalWindow::GetFrames(nsIDOMWindow
** aFrames
)
5749 FORWARD_TO_OUTER(GetFrames
, (aFrames
), NS_ERROR_NOT_INITIALIZED
);
5752 NS_ADDREF(*aFrames
);
5754 FlushPendingNotifications(Flush_ContentAndNotify
);
5760 nsGlobalWindow::CallerInnerWindow()
5762 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
5764 NS_ERROR("Please don't call this method from C++!");
5769 JSObject
*scope
= nsnull
;
5770 JSStackFrame
*fp
= nsnull
;
5771 JS_FrameIterator(cx
, &fp
);
5773 while (fp
->isDummyFrame()) {
5774 if (!JS_FrameIterator(cx
, &fp
))
5779 scope
= &fp
->scopeChain();
5783 scope
= JS_GetScopeChain(cx
);
5785 JSAutoEnterCompartment ac
;
5786 if (!ac
.enter(cx
, scope
))
5789 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
5790 nsContentUtils::XPConnect()->
5791 GetWrappedNativeOfJSObject(cx
, ::JS_GetGlobalForObject(cx
, scope
),
5792 getter_AddRefs(wrapper
));
5796 // The calling window must be holding a reference, so we can just return a
5797 // raw pointer here and let the QI's addref be balanced by the nsCOMPtr
5798 // destructor's release.
5799 nsCOMPtr
<nsPIDOMWindow
> win
= do_QueryWrappedNative(wrapper
);
5801 return GetCurrentInnerWindowInternal();
5802 return static_cast<nsGlobalWindow
*>(win
.get());
5807 * Class used to represent events generated by calls to Window.postMessage,
5808 * which asynchronously creates and dispatches events.
5810 class PostMessageEvent
: public nsRunnable
5815 PostMessageEvent(nsGlobalWindow
* aSource
,
5816 const nsAString
& aCallerOrigin
,
5817 const nsAString
& aMessage
,
5818 nsGlobalWindow
* aTargetWindow
,
5819 nsIURI
* aProvidedOrigin
,
5820 PRBool aTrustedCaller
)
5822 mCallerOrigin(aCallerOrigin
),
5824 mTargetWindow(aTargetWindow
),
5825 mProvidedOrigin(aProvidedOrigin
),
5826 mTrustedCaller(aTrustedCaller
)
5828 MOZ_COUNT_CTOR(PostMessageEvent
);
5833 MOZ_COUNT_DTOR(PostMessageEvent
);
5837 nsRefPtr
<nsGlobalWindow
> mSource
;
5838 nsString mCallerOrigin
;
5840 nsRefPtr
<nsGlobalWindow
> mTargetWindow
;
5841 nsCOMPtr
<nsIURI
> mProvidedOrigin
;
5842 PRBool mTrustedCaller
;
5846 PostMessageEvent::Run()
5848 NS_ABORT_IF_FALSE(mTargetWindow
->IsOuterWindow(),
5849 "should have been passed an outer window!");
5850 NS_ABORT_IF_FALSE(!mSource
|| mSource
->IsOuterWindow(),
5851 "should have been passed an outer window!");
5853 nsRefPtr
<nsGlobalWindow
> targetWindow
;
5854 if (mTargetWindow
->IsClosedOrClosing() ||
5855 !(targetWindow
= mTargetWindow
->GetCurrentInnerWindowInternal()) ||
5856 targetWindow
->IsClosedOrClosing())
5859 NS_ABORT_IF_FALSE(targetWindow
->IsInnerWindow(),
5860 "we ordered an inner window!");
5862 // Ensure that any origin which might have been provided is the origin of this
5863 // window's document. Note that we do this *now* instead of when postMessage
5864 // is called because the target window might have been navigated to a
5865 // different location between then and now. If this check happened when
5866 // postMessage was called, it would be fairly easy for a malicious webpage to
5867 // intercept messages intended for another site by carefully timing navigation
5868 // of the target window so it changed location after postMessage but before
5870 if (mProvidedOrigin
) {
5871 // Get the target's origin either from its principal or, in the case the
5872 // principal doesn't carry a URI (e.g. the system principal), the target's
5874 nsIPrincipal
* targetPrin
= targetWindow
->GetPrincipal();
5877 nsCOMPtr
<nsIURI
> targetURI
;
5878 if (NS_FAILED(targetPrin
->GetURI(getter_AddRefs(targetURI
))))
5881 targetURI
= targetWindow
->mDoc
->GetDocumentURI();
5886 // Note: This is contrary to the spec with respect to file: URLs, which
5887 // the spec groups into a single origin, but given we intentionally
5888 // don't do that in other places it seems better to hold the line for
5889 // now. Long-term, we want HTML5 to address this so that we can
5890 // be compliant while being safer.
5891 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
5893 ssm
->CheckSameOriginURI(mProvidedOrigin
, targetURI
, PR_TRUE
);
5900 nsCOMPtr
<nsIDOMDocumentEvent
> docEvent
=
5901 do_QueryInterface(targetWindow
->mDocument
);
5904 nsCOMPtr
<nsIDOMEvent
> event
;
5905 docEvent
->CreateEvent(NS_LITERAL_STRING("MessageEvent"),
5906 getter_AddRefs(event
));
5910 nsCOMPtr
<nsIDOMMessageEvent
> message
= do_QueryInterface(event
);
5911 nsresult rv
= message
->InitMessageEvent(NS_LITERAL_STRING("message"),
5912 PR_FALSE
/* non-bubbling */,
5913 PR_TRUE
/* cancelable */,
5922 // We can't simply call dispatchEvent on the window because doing so ends
5923 // up flipping the trusted bit on the event, and we don't want that to
5924 // happen because then untrusted content can call postMessage on a chrome
5925 // window if it can get a reference to it.
5927 nsIPresShell
*shell
= targetWindow
->mDoc
->GetShell();
5928 nsRefPtr
<nsPresContext
> presContext
;
5930 presContext
= shell
->GetPresContext();
5932 nsCOMPtr
<nsIPrivateDOMEvent
> privEvent
= do_QueryInterface(message
);
5933 privEvent
->SetTrusted(mTrustedCaller
);
5934 nsEvent
*internalEvent
= privEvent
->GetInternalNSEvent();
5936 nsEventStatus status
= nsEventStatus_eIgnore
;
5937 nsEventDispatcher::Dispatch(static_cast<nsPIDOMWindow
*>(mTargetWindow
),
5946 nsGlobalWindow::PostMessageMoz(const nsAString
& aMessage
, const nsAString
& aOrigin
)
5948 FORWARD_TO_OUTER(PostMessageMoz
, (aMessage
, aOrigin
), NS_ERROR_NOT_INITIALIZED
);
5951 // Window.postMessage is an intentional subversion of the same-origin policy.
5952 // As such, this code must be particularly careful in the information it
5953 // exposes to calling code.
5955 // http://www.whatwg.org/specs/web-apps/current-work/multipage/section-crossDocumentMessages.html
5958 // First, get the caller's window
5959 nsRefPtr
<nsGlobalWindow
> callerInnerWin
= CallerInnerWindow();
5960 if (!callerInnerWin
)
5962 NS_ABORT_IF_FALSE(callerInnerWin
->IsInnerWindow(),
5963 "should have gotten an inner window here");
5965 // Compute the caller's origin either from its principal or, in the case the
5966 // principal doesn't carry a URI (e.g. the system principal), the caller's
5967 // document. We must get this now instead of when the event is created and
5968 // dispatched, because ultimately it is the identity of the calling window
5969 // *now* that determines who sent the message (and not an identity which might
5970 // have changed due to intervening navigations).
5971 nsIPrincipal
* callerPrin
= callerInnerWin
->GetPrincipal();
5975 nsCOMPtr
<nsIURI
> callerOuterURI
;
5976 if (NS_FAILED(callerPrin
->GetURI(getter_AddRefs(callerOuterURI
))))
5979 nsAutoString origin
;
5980 if (callerOuterURI
) {
5981 // if the principal has a URI, use that to generate the origin
5982 nsContentUtils::GetUTFOrigin(callerPrin
, origin
);
5985 // otherwise use the URI of the document to generate origin
5986 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(callerInnerWin
->mDocument
);
5989 callerOuterURI
= doc
->GetDocumentURI();
5990 // if the principal has a URI, use that to generate the origin
5991 nsContentUtils::GetUTFOrigin(callerOuterURI
, origin
);
5994 // Convert the provided origin string into a URI for comparison purposes.
5995 // "*" indicates no specific origin is required.
5996 nsCOMPtr
<nsIURI
> providedOrigin
;
5997 if (!aOrigin
.EqualsASCII("*")) {
5998 if (NS_FAILED(NS_NewURI(getter_AddRefs(providedOrigin
), aOrigin
)))
5999 return NS_ERROR_DOM_SYNTAX_ERR
;
6000 if (NS_FAILED(providedOrigin
->SetUserPass(EmptyCString())) ||
6001 NS_FAILED(providedOrigin
->SetPath(EmptyCString())))
6005 // Create and asynchronously dispatch a runnable which will handle actual DOM
6006 // event creation and dispatch.
6007 nsRefPtr
<PostMessageEvent
> event
=
6008 new PostMessageEvent(nsContentUtils::IsCallerChrome()
6010 : callerInnerWin
->GetOuterWindowInternal(),
6015 nsContentUtils::IsCallerTrustedForWrite());
6016 return NS_DispatchToCurrentThread(event
);
6019 class nsCloseEvent
: public nsRunnable
{
6021 nsRefPtr
<nsGlobalWindow
> mWindow
;
6023 nsCloseEvent(nsGlobalWindow
*aWindow
)
6030 PostCloseEvent(nsGlobalWindow
* aWindow
) {
6031 nsCOMPtr
<nsIRunnable
> ev
= new nsCloseEvent(aWindow
);
6032 nsresult rv
= NS_DispatchToCurrentThread(ev
);
6033 if (NS_SUCCEEDED(rv
))
6034 aWindow
->MaybeForgiveSpamCount();
6040 mWindow
->ReallyCloseWindow();
6047 nsGlobalWindow::CanClose()
6052 // Ask the content viewer whether the toplevel window can close.
6053 // If the content viewer returns false, it is responsible for calling
6054 // Close() as soon as it is possible for the window to close.
6055 // This allows us to not close the window while printing is happening.
6057 nsCOMPtr
<nsIContentViewer
> cv
;
6058 mDocShell
->GetContentViewer(getter_AddRefs(cv
));
6061 nsresult rv
= cv
->PermitUnload(PR_FALSE
, &canClose
);
6062 if (NS_SUCCEEDED(rv
) && !canClose
)
6065 rv
= cv
->RequestWindowClose(&canClose
);
6066 if (NS_SUCCEEDED(rv
) && !canClose
)
6074 nsGlobalWindow::Close()
6076 FORWARD_TO_OUTER(Close
, (), NS_ERROR_NOT_INITIALIZED
);
6078 if (IsFrame() || !mDocShell
|| IsInModalState()) {
6079 // window.close() is called on a frame in a frameset, on a window
6080 // that's already closed, or on a window for which there's
6081 // currently a modal dialog open. Ignore such calls.
6086 if (mHavePendingClose
) {
6087 // We're going to be closed anyway; do nothing since we don't want
6092 if (mBlockScriptedClosingFlag
)
6094 // A script's popup has been blocked and we don't want
6095 // the window to be closed directly after this event,
6096 // so the user can see that there was a blocked popup.
6100 // Don't allow scripts from content to close windows
6101 // that were not opened by script
6102 if (!mHadOriginalOpener
&& !nsContentUtils::IsCallerTrustedForWrite()) {
6104 nsContentUtils::GetBoolPref("dom.allow_scripts_to_close_windows",
6107 // We're blocking the close operation
6108 // report localized error msg in JS console
6109 nsContentUtils::ReportToConsole(
6110 nsContentUtils::eDOM_PROPERTIES
,
6111 "WindowCloseBlockedWarning",
6112 nsnull
, 0, // No params
6114 EmptyString(), 0, 0, // No source, or column/line number
6115 nsIScriptError::warningFlag
,
6116 "DOM Window", mDoc
); // Better name for the category?
6122 if (!mInClose
&& !mIsClosed
&& !CanClose())
6125 // Fire a DOM event notifying listeners that this window is about to
6126 // be closed. The tab UI code may choose to cancel the default
6127 // action for this event, if so, we won't actually close the window
6128 // (since the tab UI code will close the tab in stead). Sure, this
6129 // could be abused by content code, but do we care? I don't think
6132 PRBool wasInClose
= mInClose
;
6135 if (!DispatchCustomEvent("DOMWindowClose")) {
6136 // Someone chose to prevent the default action for this event, if
6137 // so, let's not close this window after all...
6139 mInClose
= wasInClose
;
6143 return FinalClose();
6147 nsGlobalWindow::ForceClose()
6149 if (IsFrame() || !mDocShell
) {
6150 // This may be a frame in a frameset, or a window that's already closed.
6151 // Ignore such calls.
6156 if (mHavePendingClose
) {
6157 // We're going to be closed anyway; do nothing since we don't want
6164 DispatchCustomEvent("DOMWindowClose");
6166 return FinalClose();
6170 nsGlobalWindow::FinalClose()
6173 // Flag that we were closed.
6174 mIsClosed
= PR_TRUE
;
6176 nsCOMPtr
<nsIJSContextStack
> stack
=
6177 do_GetService(sJSStackContractID
);
6179 JSContext
*cx
= nsnull
;
6186 nsIScriptContext
*currentCX
= nsJSUtils::GetDynamicScriptContext(cx
);
6188 if (currentCX
&& currentCX
== GetContextInternal()) {
6189 // We ignore the return value here. If setting the termination function
6190 // fails, it's better to fail to close the window than it is to crash
6191 // (which is what would tend to happen if we did this synchronously
6193 rv
= currentCX
->SetTerminationFunction(CloseWindow
,
6194 static_cast<nsIDOMWindow
*>
6196 if (NS_SUCCEEDED(rv
)) {
6197 mHavePendingClose
= PR_TRUE
;
6204 // We may have plugins on the page that have issued this close from their
6205 // event loop and because we currently destroy the plugin window with
6206 // frames, we crash. So, if we are called from Javascript, post an event
6207 // to really close the window.
6208 rv
= NS_ERROR_FAILURE
;
6209 if (!nsContentUtils::IsCallerChrome()) {
6210 rv
= nsCloseEvent::PostCloseEvent(this);
6213 if (NS_FAILED(rv
)) {
6214 ReallyCloseWindow();
6217 mHavePendingClose
= PR_TRUE
;
6225 nsGlobalWindow::ReallyCloseWindow()
6227 FORWARD_TO_OUTER_VOID(ReallyCloseWindow
, ());
6229 // Make sure we never reenter this method.
6230 mHavePendingClose
= PR_TRUE
;
6232 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
6233 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
6235 // If there's no treeOwnerAsWin, this window must already be closed.
6237 if (treeOwnerAsWin
) {
6239 // but if we're a browser window we could be in some nasty
6240 // self-destroying cascade that we should mostly ignore
6242 nsCOMPtr
<nsIDocShellTreeItem
> docItem(do_QueryInterface(mDocShell
));
6244 nsCOMPtr
<nsIBrowserDOMWindow
> bwin
;
6245 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
6246 docItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
6247 nsCOMPtr
<nsIDOMWindow
> rootWin(do_GetInterface(rootItem
));
6248 nsCOMPtr
<nsIDOMChromeWindow
> chromeWin(do_QueryInterface(rootWin
));
6250 chromeWin
->GetBrowserDOMWindow(getter_AddRefs(bwin
));
6253 /* Normally we destroy the entire window, but not if
6254 this DOM window belongs to a tabbed browser and doesn't
6255 correspond to a tab. This allows a well-behaved tab
6256 to destroy the container as it should but is a final measure
6257 to prevent an errant tab from doing so when it shouldn't.
6258 This works because we reach this code when we shouldn't only
6259 in the particular circumstance that we belong to a tab
6260 that has just been closed (and is therefore already missing
6261 from the list of browsers) (and has an unload handler
6262 that closes the window). */
6263 // XXXbz now that we have mHavePendingClose, is this needed?
6264 PRBool isTab
= PR_FALSE
;
6265 if (rootWin
== this ||
6266 !bwin
|| (bwin
->IsTabContentWindow(GetOuterWindowInternal(),
6268 treeOwnerAsWin
->Destroy();
6277 nsGlobalWindow::EnterModalState()
6279 nsGlobalWindow
* topWin
= GetTop();
6282 NS_ERROR("Uh, EnterModalState() called w/o a reachable top window?");
6287 // If there is an active ESM in this window, clear it. Otherwise, this can
6288 // cause a problem if a modal state is entered during a mouseup event.
6289 nsEventStateManager
* activeESM
=
6290 static_cast<nsEventStateManager
*>(nsEventStateManager::GetActiveEventStateManager());
6291 if (activeESM
&& activeESM
->GetPresContext()) {
6292 nsIPresShell
* activeShell
= activeESM
->GetPresContext()->GetPresShell();
6293 if (activeShell
&& (
6294 nsContentUtils::ContentIsCrossDocDescendantOf(activeShell
->GetDocument(), mDoc
) ||
6295 nsContentUtils::ContentIsCrossDocDescendantOf(mDoc
, activeShell
->GetDocument()))) {
6296 nsEventStateManager::ClearGlobalActiveContent(activeESM
);
6298 activeShell
->SetCapturingContent(nsnull
, 0);
6301 nsCOMPtr
<nsFrameSelection
> frameSelection
= activeShell
->FrameSelection();
6302 frameSelection
->SetMouseDownState(PR_FALSE
);
6307 if (topWin
->mModalStateDepth
== 0) {
6308 NS_ASSERTION(!mSuspendedDoc
, "Shouldn't have mSuspendedDoc here!");
6310 mSuspendedDoc
= do_QueryInterface(topWin
->GetExtantDocument());
6311 if (mSuspendedDoc
&& mSuspendedDoc
->EventHandlingSuppressed()) {
6312 mSuspendedDoc
->SuppressEventHandling();
6314 mSuspendedDoc
= nsnull
;
6317 topWin
->mModalStateDepth
++;
6319 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
6321 nsCOMPtr
<nsIDOMWindow
> callerWin
;
6322 nsIScriptContext
*scx
;
6323 if (cx
&& (scx
= GetScriptContextFromJSContext(cx
))) {
6324 scx
->EnterModalState();
6325 callerWin
= do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx
));
6329 mContext
->EnterModalState();
6337 nsGlobalWindow::RunPendingTimeoutsRecursive(nsGlobalWindow
*aTopWindow
,
6338 nsGlobalWindow
*aWindow
)
6340 nsGlobalWindow
*inner
;
6342 // Return early if we're frozen or have no inner window.
6343 if (!(inner
= aWindow
->GetCurrentInnerWindowInternal()) ||
6344 inner
->IsFrozen()) {
6348 inner
->RunTimeout(nsnull
);
6350 // Check again if we're frozen since running pending timeouts
6351 // could've frozen us.
6352 if (inner
->IsFrozen()) {
6356 nsCOMPtr
<nsIDOMWindowCollection
> frames
;
6357 aWindow
->GetFrames(getter_AddRefs(frames
));
6364 if (NS_FAILED(frames
->GetLength(&length
)) || !length
) {
6368 for (i
= 0; i
< length
&& aTopWindow
->mModalStateDepth
== 0; i
++) {
6369 nsCOMPtr
<nsIDOMWindow
> child
;
6370 frames
->Item(i
, getter_AddRefs(child
));
6376 nsGlobalWindow
*childWin
=
6377 static_cast<nsGlobalWindow
*>
6378 (static_cast<nsIDOMWindow
*>
6381 RunPendingTimeoutsRecursive(aTopWindow
, childWin
);
6385 class nsPendingTimeoutRunner
: public nsRunnable
6388 nsPendingTimeoutRunner(nsGlobalWindow
*aWindow
)
6391 NS_ASSERTION(mWindow
, "mWindow is null.");
6396 nsGlobalWindow::RunPendingTimeoutsRecursive(mWindow
, mWindow
);
6402 nsRefPtr
<nsGlobalWindow
> mWindow
;
6406 nsGlobalWindow::LeaveModalState(nsIDOMWindow
*aCallerWin
)
6408 nsGlobalWindow
*topWin
= GetTop();
6411 NS_ERROR("Uh, LeaveModalState() called w/o a reachable top window?");
6415 topWin
->mModalStateDepth
--;
6417 if (topWin
->mModalStateDepth
== 0) {
6418 nsCOMPtr
<nsIRunnable
> runner
= new nsPendingTimeoutRunner(topWin
);
6419 if (NS_FAILED(NS_DispatchToCurrentThread(runner
)))
6420 NS_WARNING("failed to dispatch pending timeout runnable");
6422 if (mSuspendedDoc
) {
6423 nsCOMPtr
<nsIDocument
> currentDoc
=
6424 do_QueryInterface(topWin
->GetExtantDocument());
6425 mSuspendedDoc
->UnsuppressEventHandlingAndFireEvents(currentDoc
== mSuspendedDoc
);
6426 mSuspendedDoc
= nsnull
;
6430 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
6433 nsCOMPtr
<nsIScriptGlobalObject
> sgo(do_QueryInterface(aCallerWin
));
6434 nsIScriptContext
*scx
= sgo
->GetContext();
6435 scx
->LeaveModalState();
6439 mContext
->LeaveModalState();
6442 // Remember the time of the last dialog quit.
6443 nsGlobalWindow
*inner
= topWin
->GetCurrentInnerWindowInternal();
6445 inner
->mLastDialogQuitTime
= TimeStamp::Now();
6449 nsGlobalWindow::IsInModalState()
6451 nsGlobalWindow
*topWin
= GetTop();
6454 NS_ERROR("Uh, IsInModalState() called w/o a reachable top window?");
6459 return topWin
->mModalStateDepth
!= 0;
6464 nsGlobalWindow::NotifyDOMWindowDestroyed(nsGlobalWindow
* aWindow
) {
6465 nsCOMPtr
<nsIObserverService
> observerService
=
6466 do_GetService(NS_OBSERVERSERVICE_CONTRACTID
);
6467 if (observerService
) {
6469 NotifyObservers(static_cast<nsIScriptGlobalObject
*>(aWindow
),
6470 DOM_WINDOW_DESTROYED_TOPIC
, nsnull
);
6474 class WindowDestroyedEvent
: public nsRunnable
6477 WindowDestroyedEvent(PRUint64 aID
, const char* aTopic
) :
6478 mID(aID
), mTopic(aTopic
) {}
6482 nsCOMPtr
<nsIObserverService
> observerService
=
6483 do_GetService("@mozilla.org/observer-service;1");
6484 if (observerService
) {
6485 nsCOMPtr
<nsISupportsPRUint64
> wrapper
=
6486 do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID
);
6488 wrapper
->SetData(mID
);
6489 observerService
->NotifyObservers(wrapper
, mTopic
.get(), nsnull
);
6501 nsGlobalWindow::NotifyWindowIDDestroyed(const char* aTopic
)
6503 nsRefPtr
<nsIRunnable
> runnable
= new WindowDestroyedEvent(mWindowID
, aTopic
);
6504 nsresult rv
= NS_DispatchToCurrentThread(runnable
);
6505 if (NS_SUCCEEDED(rv
)) {
6506 mNotifiedIDDestroyed
= PR_TRUE
;
6511 nsGlobalWindow::InitJavaProperties()
6513 nsIScriptContext
*scx
= GetContextInternal();
6515 if (mDidInitJavaProperties
|| IsOuterWindow() || !scx
|| !mJSObject
) {
6519 // Set mDidInitJavaProperties to true here even if initialization
6520 // can fail. If it fails, we won't try again...
6521 mDidInitJavaProperties
= PR_TRUE
;
6523 // Check whether the plugin supports NPRuntime, if so, init through
6526 nsCOMPtr
<nsIPluginHost
> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID
));
6531 mDummyJavaPluginOwner
= new nsDummyJavaPluginOwner(mDoc
);
6532 if (!mDummyJavaPluginOwner
) {
6536 host
->InstantiateDummyJavaPlugin(mDummyJavaPluginOwner
);
6538 // It's possible for us (or the Java plugin, rather) to process
6539 // events during the above call, which can lead to this window being
6540 // torn down or what not, so re-check that the dummy plugin is still
6542 if (!mDummyJavaPluginOwner
) {
6546 nsCOMPtr
<nsIPluginInstance
> dummyPlugin
;
6547 mDummyJavaPluginOwner
->GetInstance(*getter_AddRefs(dummyPlugin
));
6550 // A dummy plugin was instantiated. This means we have a Java
6551 // plugin that supports NPRuntime. For such a plugin, the plugin
6552 // instantiation code defines the Java properties for us, so we're
6558 // No NPRuntime enabled Java plugin found, null out the owner we
6559 // would have used in that case as it's no longer needed.
6560 mDummyJavaPluginOwner
= nsnull
;
6564 nsGlobalWindow::GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler
* aKey
)
6566 void* handler
= nsnull
;
6567 if (mCachedXBLPrototypeHandlers
.IsInitialized()) {
6568 mCachedXBLPrototypeHandlers
.Get(aKey
, &handler
);
6574 nsGlobalWindow::CacheXBLPrototypeHandler(nsXBLPrototypeHandler
* aKey
,
6575 nsScriptObjectHolder
& aHandler
)
6577 if (!mCachedXBLPrototypeHandlers
.IsInitialized() &&
6578 !mCachedXBLPrototypeHandlers
.Init()) {
6579 NS_ERROR("Failed to initiailize hashtable!");
6583 if (!mCachedXBLPrototypeHandlers
.Count()) {
6584 // Can't use macros to get the participant because nsGlobalChromeWindow also
6585 // runs through this code. Use QueryInterface to get the correct objects.
6586 nsXPCOMCycleCollectionParticipant
* participant
;
6587 CallQueryInterface(this, &participant
);
6588 NS_ASSERTION(participant
,
6589 "Failed to QI to nsXPCOMCycleCollectionParticipant!");
6591 nsISupports
* thisSupports
;
6592 QueryInterface(NS_GET_IID(nsCycleCollectionISupports
),
6593 reinterpret_cast<void**>(&thisSupports
));
6594 NS_ASSERTION(thisSupports
, "Failed to QI to nsCycleCollectionISupports!");
6596 nsresult rv
= nsContentUtils::HoldJSObjects(thisSupports
, participant
);
6597 if (NS_FAILED(rv
)) {
6598 NS_ERROR("nsContentUtils::HoldJSObjects failed!");
6603 mCachedXBLPrototypeHandlers
.Put(aKey
, aHandler
);
6607 nsGlobalWindow::GetFrameElement(nsIDOMElement
** aFrameElement
)
6609 FORWARD_TO_OUTER(GetFrameElement
, (aFrameElement
), NS_ERROR_NOT_INITIALIZED
);
6611 *aFrameElement
= nsnull
;
6613 nsCOMPtr
<nsIDocShellTreeItem
> docShellTI(do_QueryInterface(mDocShell
));
6619 nsCOMPtr
<nsIDocShellTreeItem
> parent
;
6620 docShellTI
->GetSameTypeParent(getter_AddRefs(parent
));
6622 if (!parent
|| parent
== docShellTI
) {
6623 // We're at a chrome boundary, don't expose the chrome iframe
6624 // element to content code.
6629 *aFrameElement
= mFrameElement
;
6630 NS_IF_ADDREF(*aFrameElement
);
6635 // Helper for converting window.showModalDialog() options (list of ';'
6636 // separated name (:|=) value pairs) to a format that's parsable by
6637 // our normal window opening code.
6640 ConvertDialogOptions(const nsAString
& aOptions
, nsAString
& aResult
)
6642 nsAString::const_iterator end
;
6643 aOptions
.EndReading(end
);
6645 nsAString::const_iterator iter
;
6646 aOptions
.BeginReading(iter
);
6648 while (iter
!= end
) {
6650 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6654 nsAString::const_iterator name_start
= iter
;
6656 // Skip characters until we find whitespace, ';', ':', or '='
6657 while (iter
!= end
&& !nsCRT::IsAsciiSpace(*iter
) &&
6664 nsAString::const_iterator name_end
= iter
;
6667 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6672 // No value found, skip the ';' and keep going.
6678 nsAString::const_iterator value_start
= iter
;
6679 nsAString::const_iterator value_end
= iter
;
6681 if (*iter
== ':' || *iter
== '=') {
6682 // We found name followed by ':' or '='. Look for a value.
6684 iter
++; // Skip the ':' or '='
6687 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6693 // Skip until we find whitespace, or ';'.
6694 while (iter
!= end
&& !nsCRT::IsAsciiSpace(*iter
) &&
6702 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6707 const nsDependentSubstring
& name
= Substring(name_start
, name_end
);
6708 const nsDependentSubstring
& value
= Substring(value_start
, value_end
);
6710 if (name
.LowerCaseEqualsLiteral("center")) {
6711 if (value
.LowerCaseEqualsLiteral("on") ||
6712 value
.LowerCaseEqualsLiteral("yes") ||
6713 value
.LowerCaseEqualsLiteral("1")) {
6714 aResult
.AppendLiteral(",centerscreen=1");
6716 } else if (name
.LowerCaseEqualsLiteral("dialogwidth")) {
6717 if (!value
.IsEmpty()) {
6718 aResult
.AppendLiteral(",width=");
6719 aResult
.Append(value
);
6721 } else if (name
.LowerCaseEqualsLiteral("dialogheight")) {
6722 if (!value
.IsEmpty()) {
6723 aResult
.AppendLiteral(",height=");
6724 aResult
.Append(value
);
6726 } else if (name
.LowerCaseEqualsLiteral("dialogtop")) {
6727 if (!value
.IsEmpty()) {
6728 aResult
.AppendLiteral(",top=");
6729 aResult
.Append(value
);
6731 } else if (name
.LowerCaseEqualsLiteral("dialogleft")) {
6732 if (!value
.IsEmpty()) {
6733 aResult
.AppendLiteral(",left=");
6734 aResult
.Append(value
);
6736 } else if (name
.LowerCaseEqualsLiteral("resizable")) {
6737 if (value
.LowerCaseEqualsLiteral("on") ||
6738 value
.LowerCaseEqualsLiteral("yes") ||
6739 value
.LowerCaseEqualsLiteral("1")) {
6740 aResult
.AppendLiteral(",resizable=1");
6742 } else if (name
.LowerCaseEqualsLiteral("scroll")) {
6743 if (value
.LowerCaseEqualsLiteral("off") ||
6744 value
.LowerCaseEqualsLiteral("no") ||
6745 value
.LowerCaseEqualsLiteral("0")) {
6746 aResult
.AppendLiteral(",scrollbars=0");
6759 nsGlobalWindow::ShowModalDialog(const nsAString
& aURI
, nsIVariant
*aArgs
,
6760 const nsAString
& aOptions
,
6761 nsIVariant
**aRetVal
)
6763 FORWARD_TO_OUTER(ShowModalDialog
, (aURI
, aArgs
, aOptions
, aRetVal
),
6764 NS_ERROR_NOT_INITIALIZED
);
6768 // Before bringing up the window/dialog, unsuppress painting and flush
6770 EnsureReflowFlushAndPaint();
6772 if (AreDialogsBlocked() || !ConfirmDialogAllowed())
6773 return NS_ERROR_NOT_AVAILABLE
;
6775 nsCOMPtr
<nsIDOMWindow
> dlgWin
;
6776 nsAutoString
options(NS_LITERAL_STRING("-moz-internal-modal=1,status=1"));
6778 ConvertDialogOptions(aOptions
, options
);
6780 options
.AppendLiteral(",scrollbars=1,centerscreen=1,resizable=0");
6783 nsresult rv
= OpenInternal(aURI
, EmptyString(), options
,
6784 PR_FALSE
, // aDialog
6785 PR_TRUE
, // aContentModal
6786 PR_TRUE
, // aCalledNoScript
6787 PR_TRUE
, // aDoJSFixups
6788 nsnull
, aArgs
, // args
6789 GetPrincipal(), // aCalleePrincipal
6790 nsnull
, // aJSCallerContext
6791 getter_AddRefs(dlgWin
));
6792 LeaveModalState(nsnull
);
6794 NS_ENSURE_SUCCESS(rv
, rv
);
6797 nsCOMPtr
<nsIPrincipal
> subjectPrincipal
;
6798 rv
= nsContentUtils::GetSecurityManager()->
6799 GetSubjectPrincipal(getter_AddRefs(subjectPrincipal
));
6800 if (NS_FAILED(rv
)) {
6804 PRBool canAccess
= PR_TRUE
;
6806 if (subjectPrincipal
) {
6807 nsCOMPtr
<nsIScriptObjectPrincipal
> objPrincipal
=
6808 do_QueryInterface(dlgWin
);
6809 nsCOMPtr
<nsIPrincipal
> dialogPrincipal
;
6812 dialogPrincipal
= objPrincipal
->GetPrincipal();
6814 rv
= subjectPrincipal
->Subsumes(dialogPrincipal
, &canAccess
);
6815 NS_ENSURE_SUCCESS(rv
, rv
);
6817 // Uh, not sure what kind of dialog this is. Prevent access to
6818 // be on the safe side...
6820 canAccess
= PR_FALSE
;
6824 nsCOMPtr
<nsPIDOMWindow
> win(do_QueryInterface(dlgWin
));
6827 nsPIDOMWindow
*inner
= win
->GetCurrentInnerWindow();
6829 nsCOMPtr
<nsIDOMModalContentWindow
> dlgInner(do_QueryInterface(inner
));
6832 dlgInner
->GetReturnValue(aRetVal
);
6836 nsRefPtr
<nsGlobalWindow
> winInternal
=
6837 static_cast<nsGlobalWindow
*>(win
.get());
6838 if (winInternal
->mCallCleanUpAfterModalDialogCloses
) {
6839 winInternal
->mCallCleanUpAfterModalDialogCloses
= PR_FALSE
;
6840 winInternal
->CleanUp(PR_TRUE
);
6847 class CommandDispatcher
: public nsRunnable
6850 CommandDispatcher(nsIDOMXULCommandDispatcher
* aDispatcher
,
6851 const nsAString
& aAction
)
6852 : mDispatcher(aDispatcher
), mAction(aAction
) {}
6856 return mDispatcher
->UpdateCommands(mAction
);
6859 nsCOMPtr
<nsIDOMXULCommandDispatcher
> mDispatcher
;
6864 nsGlobalWindow::UpdateCommands(const nsAString
& anAction
)
6866 nsPIDOMWindow
*rootWindow
= nsGlobalWindow::GetPrivateRoot();
6870 nsCOMPtr
<nsIDOMXULDocument
> xulDoc
=
6871 do_QueryInterface(rootWindow
->GetExtantDocument());
6872 // See if we contain a XUL document.
6874 // Retrieve the command dispatcher and call updateCommands on it.
6875 nsCOMPtr
<nsIDOMXULCommandDispatcher
> xulCommandDispatcher
;
6876 xulDoc
->GetCommandDispatcher(getter_AddRefs(xulCommandDispatcher
));
6877 if (xulCommandDispatcher
) {
6878 nsContentUtils::AddScriptRunner(new CommandDispatcher(xulCommandDispatcher
,
6887 nsGlobalWindow::GetBlurSuppression()
6889 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
6890 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
6891 PRBool suppress
= PR_FALSE
;
6893 treeOwnerAsWin
->GetBlurSuppression(&suppress
);
6898 nsGlobalWindow::GetSelection(nsISelection
** aSelection
)
6900 FORWARD_TO_OUTER(GetSelection
, (aSelection
), NS_ERROR_NOT_INITIALIZED
);
6902 NS_ENSURE_ARG_POINTER(aSelection
);
6903 *aSelection
= nsnull
;
6908 nsCOMPtr
<nsIPresShell
> presShell
;
6909 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
6914 *aSelection
= presShell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
6916 NS_IF_ADDREF(*aSelection
);
6922 nsGlobalWindow::Find(const nsAString
& aStr
, PRBool aCaseSensitive
,
6923 PRBool aBackwards
, PRBool aWrapAround
, PRBool aWholeWord
,
6924 PRBool aSearchInFrames
, PRBool aShowDialog
,
6927 FORWARD_TO_OUTER(Find
, (aStr
, aCaseSensitive
, aBackwards
, aWrapAround
,
6928 aWholeWord
, aSearchInFrames
, aShowDialog
, aDidFind
),
6929 NS_ERROR_NOT_INITIALIZED
);
6931 nsresult rv
= NS_OK
;
6932 *aDidFind
= PR_FALSE
;
6934 nsCOMPtr
<nsIWebBrowserFind
> finder(do_GetInterface(mDocShell
));
6935 NS_ENSURE_TRUE(finder
, NS_ERROR_FAILURE
);
6937 // Set the options of the search
6938 rv
= finder
->SetSearchString(PromiseFlatString(aStr
).get());
6939 NS_ENSURE_SUCCESS(rv
, rv
);
6940 finder
->SetMatchCase(aCaseSensitive
);
6941 finder
->SetFindBackwards(aBackwards
);
6942 finder
->SetWrapFind(aWrapAround
);
6943 finder
->SetEntireWord(aWholeWord
);
6944 finder
->SetSearchFrames(aSearchInFrames
);
6946 // the nsIWebBrowserFind is initialized to use this window
6947 // as the search root, but uses focus to set the current search
6948 // frame. If we're being called from JS (as here), this window
6949 // should be the current search frame.
6950 nsCOMPtr
<nsIWebBrowserFindInFrames
> framesFinder(do_QueryInterface(finder
));
6952 framesFinder
->SetRootSearchFrame(this); // paranoia
6953 framesFinder
->SetCurrentSearchFrame(this);
6956 // The Find API does not accept empty strings. Launch the Find Dialog.
6957 if (aStr
.IsEmpty() || aShowDialog
) {
6958 // See if the find dialog is already up using nsIWindowMediator
6959 nsCOMPtr
<nsIWindowMediator
> windowMediator
=
6960 do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
);
6962 nsCOMPtr
<nsIDOMWindowInternal
> findDialog
;
6964 if (windowMediator
) {
6965 windowMediator
->GetMostRecentWindow(NS_LITERAL_STRING("findInPage").get(),
6966 getter_AddRefs(findDialog
));
6970 // The Find dialog is already open, bring it to the top.
6971 rv
= findDialog
->Focus();
6972 } else { // Open a Find dialog
6974 nsCOMPtr
<nsIDOMWindow
> dialog
;
6975 rv
= OpenDialog(NS_LITERAL_STRING("chrome://global/content/finddialog.xul"),
6976 NS_LITERAL_STRING("_blank"),
6977 NS_LITERAL_STRING("chrome, resizable=no, dependent=yes"),
6978 finder
, getter_AddRefs(dialog
));
6982 // Launch the search with the passed in search string
6983 rv
= finder
->FindNext(aDidFind
);
6984 NS_ENSURE_SUCCESS(rv
, rv
);
6991 Is8bit(const nsAString
& aString
)
6993 static const PRUnichar EIGHT_BIT
= PRUnichar(~0x00FF);
6995 nsAString::const_iterator done_reading
;
6996 aString
.EndReading(done_reading
);
6998 // for each chunk of |aString|...
6999 PRUint32 fragmentLength
= 0;
7000 nsAString::const_iterator iter
;
7001 for (aString
.BeginReading(iter
); iter
!= done_reading
;
7002 iter
.advance(PRInt32(fragmentLength
))) {
7003 fragmentLength
= PRUint32(iter
.size_forward());
7004 const PRUnichar
* c
= iter
.get();
7005 const PRUnichar
* fragmentEnd
= c
+ fragmentLength
;
7007 // for each character in this chunk...
7008 while (c
< fragmentEnd
)
7009 if (*c
++ & EIGHT_BIT
)
7017 nsGlobalWindow::Atob(const nsAString
& aAsciiBase64String
,
7018 nsAString
& aBinaryData
)
7020 if (!Is8bit(aAsciiBase64String
)) {
7021 aBinaryData
.Truncate();
7022 return NS_ERROR_DOM_INVALID_CHARACTER_ERR
;
7025 nsresult rv
= nsXPConnect::Base64Decode(aAsciiBase64String
, aBinaryData
);
7026 if (NS_FAILED(rv
) && rv
== NS_ERROR_INVALID_ARG
) {
7027 return NS_ERROR_DOM_INVALID_CHARACTER_ERR
;
7033 nsGlobalWindow::Btoa(const nsAString
& aBinaryData
,
7034 nsAString
& aAsciiBase64String
)
7036 if (!Is8bit(aBinaryData
)) {
7037 aAsciiBase64String
.Truncate();
7038 return NS_ERROR_DOM_INVALID_CHARACTER_ERR
;
7041 return nsXPConnect::Base64Encode(aBinaryData
, aAsciiBase64String
);
7044 //*****************************************************************************
7045 // nsGlobalWindow::nsIDOMEventTarget
7046 //*****************************************************************************
7049 nsGlobalWindow::AddEventListener(const nsAString
& aType
,
7050 nsIDOMEventListener
* aListener
,
7053 FORWARD_TO_INNER_CREATE(AddEventListener
, (aType
, aListener
, aUseCapture
),
7054 NS_ERROR_NOT_AVAILABLE
);
7056 return AddEventListener(aType
, aListener
, aUseCapture
, PR_FALSE
, 0);
7060 nsGlobalWindow::RemoveEventListener(const nsAString
& aType
,
7061 nsIDOMEventListener
* aListener
,
7064 return RemoveGroupedEventListener(aType
, aListener
, aUseCapture
, nsnull
);
7068 nsGlobalWindow::DispatchEvent(nsIDOMEvent
* aEvent
, PRBool
* _retval
)
7070 FORWARD_TO_INNER(DispatchEvent
, (aEvent
, _retval
), NS_OK
);
7073 return NS_ERROR_FAILURE
;
7076 // Obtain a presentation shell
7077 nsIPresShell
*shell
= mDoc
->GetShell();
7078 nsRefPtr
<nsPresContext
> presContext
;
7080 // Retrieve the context
7081 presContext
= shell
->GetPresContext();
7084 nsEventStatus status
= nsEventStatus_eIgnore
;
7086 nsEventDispatcher::DispatchDOMEvent(GetOuterWindow(), nsnull
, aEvent
,
7087 presContext
, &status
);
7089 *_retval
= (status
!= nsEventStatus_eConsumeNoDefault
);
7093 //*****************************************************************************
7094 // nsGlobalWindow::nsIDOM3EventTarget
7095 //*****************************************************************************
7098 nsGlobalWindow::AddGroupedEventListener(const nsAString
& aType
,
7099 nsIDOMEventListener
*aListener
,
7101 nsIDOMEventGroup
*aEvtGrp
)
7103 FORWARD_TO_INNER_CREATE(AddGroupedEventListener
,
7104 (aType
, aListener
, aUseCapture
, aEvtGrp
),
7105 NS_ERROR_NOT_AVAILABLE
);
7107 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
7108 NS_ENSURE_STATE(manager
);
7109 PRInt32 flags
= aUseCapture
? NS_EVENT_FLAG_CAPTURE
: NS_EVENT_FLAG_BUBBLE
;
7110 return manager
->AddEventListenerByType(aListener
, aType
, flags
, aEvtGrp
);
7114 nsGlobalWindow::RemoveGroupedEventListener(const nsAString
& aType
,
7115 nsIDOMEventListener
*aListener
,
7117 nsIDOMEventGroup
*aEvtGrp
)
7119 FORWARD_TO_INNER(RemoveGroupedEventListener
,
7120 (aType
, aListener
, aUseCapture
, aEvtGrp
),
7121 NS_ERROR_NOT_INITIALIZED
);
7123 if (mListenerManager
) {
7124 PRInt32 flags
= aUseCapture
? NS_EVENT_FLAG_CAPTURE
: NS_EVENT_FLAG_BUBBLE
;
7126 mListenerManager
->RemoveEventListenerByType(aListener
, aType
, flags
,
7133 nsGlobalWindow::CanTrigger(const nsAString
& type
, PRBool
*_retval
)
7135 return NS_ERROR_NOT_IMPLEMENTED
;
7139 nsGlobalWindow::IsRegisteredHere(const nsAString
& type
, PRBool
*_retval
)
7141 return NS_ERROR_NOT_IMPLEMENTED
;
7145 nsGlobalWindow::AddEventListener(const nsAString
& aType
,
7146 nsIDOMEventListener
*aListener
,
7147 PRBool aUseCapture
, PRBool aWantsUntrusted
,
7148 PRUint8 optional_argc
)
7150 NS_ASSERTION(!aWantsUntrusted
|| optional_argc
> 0,
7151 "Won't check if this is chrome, you want to set "
7152 "aWantsUntrusted to PR_FALSE or make the aWantsUntrusted "
7153 "explicit by making optional_argc non-zero.");
7155 if (IsOuterWindow() && mInnerWindow
&&
7156 !nsContentUtils::CanCallerAccess(mInnerWindow
)) {
7157 return NS_ERROR_DOM_SECURITY_ERR
;
7160 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
7161 NS_ENSURE_STATE(manager
);
7163 PRInt32 flags
= aUseCapture
? NS_EVENT_FLAG_CAPTURE
: NS_EVENT_FLAG_BUBBLE
;
7165 if (aWantsUntrusted
||
7166 (optional_argc
== 0 && !nsContentUtils::IsChromeDoc(mDoc
))) {
7167 flags
|= NS_PRIV_EVENT_UNTRUSTED_PERMITTED
;
7170 return manager
->AddEventListenerByType(aListener
, aType
, flags
, nsnull
);
7174 nsGlobalWindow::AddEventListenerByIID(nsIDOMEventListener
* aListener
,
7177 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
7178 NS_ENSURE_STATE(manager
);
7179 return manager
->AddEventListenerByIID(aListener
, aIID
, NS_EVENT_FLAG_BUBBLE
);
7183 nsGlobalWindow::RemoveEventListenerByIID(nsIDOMEventListener
* aListener
,
7186 FORWARD_TO_INNER(RemoveEventListenerByIID
, (aListener
, aIID
),
7187 NS_ERROR_NOT_INITIALIZED
);
7189 if (mListenerManager
) {
7190 mListenerManager
->RemoveEventListenerByIID(aListener
, aIID
,
7191 NS_EVENT_FLAG_BUBBLE
);
7194 return NS_ERROR_FAILURE
;
7197 nsIEventListenerManager
*
7198 nsGlobalWindow::GetListenerManager(PRBool aCreateIfNotFound
)
7200 FORWARD_TO_INNER_CREATE(GetListenerManager
, (aCreateIfNotFound
), nsnull
);
7202 if (!mListenerManager
) {
7203 if (!aCreateIfNotFound
) {
7207 static NS_DEFINE_CID(kEventListenerManagerCID
,
7208 NS_EVENTLISTENERMANAGER_CID
);
7210 mListenerManager
= do_CreateInstance(kEventListenerManagerCID
);
7211 if (mListenerManager
) {
7212 mListenerManager
->SetListenerTarget(
7213 static_cast<nsPIDOMEventTarget
*>(this));
7217 return mListenerManager
;
7221 nsGlobalWindow::GetSystemEventGroup(nsIDOMEventGroup
**aGroup
)
7223 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
7224 NS_ENSURE_STATE(manager
);
7225 return manager
->GetSystemEventGroupLM(aGroup
);
7229 nsGlobalWindow::GetContextForEventHandlers(nsresult
* aRv
)
7231 nsIScriptContext
* scx
= GetContext();
7232 *aRv
= scx
? NS_OK
: NS_ERROR_UNEXPECTED
;
7236 //*****************************************************************************
7237 // nsGlobalWindow::nsPIDOMWindow
7238 //*****************************************************************************
7241 nsGlobalWindow::GetPrivateParent()
7243 FORWARD_TO_OUTER(GetPrivateParent
, (), nsnull
);
7245 nsCOMPtr
<nsIDOMWindow
> parent
;
7246 GetParent(getter_AddRefs(parent
));
7248 if (static_cast<nsIDOMWindow
*>(this) == parent
.get()) {
7249 nsCOMPtr
<nsIContent
> chromeElement(do_QueryInterface(mChromeEventHandler
));
7251 return nsnull
; // This is ok, just means a null parent.
7253 nsIDocument
* doc
= chromeElement
->GetDocument();
7255 return nsnull
; // This is ok, just means a null parent.
7257 nsIScriptGlobalObject
*globalObject
= doc
->GetScriptGlobalObject();
7259 return nsnull
; // This is ok, just means a null parent.
7261 parent
= do_QueryInterface(globalObject
);
7265 return static_cast<nsGlobalWindow
*>
7266 (static_cast<nsIDOMWindow
*>(parent
.get()));
7273 nsGlobalWindow::GetPrivateRoot()
7275 FORWARD_TO_OUTER(GetPrivateRoot
, (), nsnull
);
7277 nsCOMPtr
<nsIDOMWindow
> top
;
7278 GetTop(getter_AddRefs(top
));
7280 nsCOMPtr
<nsPIDOMWindow
> ptop
= do_QueryInterface(top
);
7281 NS_ASSERTION(ptop
, "cannot get ptop");
7285 nsIDocShell
*docShell
= ptop
->GetDocShell();
7287 // Get the chrome event handler from the doc shell, since we only
7288 // want to deal with XUL chrome handlers and not the new kind of
7289 // window root handler.
7290 nsCOMPtr
<nsIDOMEventTarget
> chromeEventHandler
;
7291 docShell
->GetChromeEventHandler(getter_AddRefs(chromeEventHandler
));
7293 nsCOMPtr
<nsIContent
> chromeElement(do_QueryInterface(mChromeEventHandler
));
7294 if (chromeElement
) {
7295 nsIDocument
* doc
= chromeElement
->GetDocument();
7297 nsIDOMWindow
*parent
= doc
->GetWindow();
7299 parent
->GetTop(getter_AddRefs(top
));
7304 return static_cast<nsGlobalWindow
*>
7305 (static_cast<nsIDOMWindow
*>(top
));
7310 nsGlobalWindow::GetLocation(nsIDOMLocation
** aLocation
)
7312 FORWARD_TO_INNER(GetLocation
, (aLocation
), NS_ERROR_NOT_INITIALIZED
);
7314 *aLocation
= nsnull
;
7316 nsIDocShell
*docShell
= GetDocShell();
7317 if (!mLocation
&& docShell
) {
7318 mLocation
= new nsLocation(docShell
);
7320 return NS_ERROR_OUT_OF_MEMORY
;
7324 NS_IF_ADDREF(*aLocation
= mLocation
);
7330 nsGlobalWindow::ActivateOrDeactivate(PRBool aActivate
)
7332 // Set / unset mIsActive on the top level window, which is used for the
7333 // :-moz-window-inactive pseudoclass.
7334 nsCOMPtr
<nsIWidget
> mainWidget
= GetMainWidget();
7338 // Get the top level widget (if the main widget is a sheet, this will
7339 // be the sheet's top (non-sheet) parent).
7340 nsCOMPtr
<nsIWidget
> topLevelWidget
= mainWidget
->GetSheetWindowParent();
7341 if (!topLevelWidget
) {
7342 topLevelWidget
= mainWidget
;
7345 // Get the top level widget's nsGlobalWindow
7346 nsCOMPtr
<nsIDOMWindowInternal
> topLevelWindow
;
7347 if (topLevelWidget
== mainWidget
) {
7348 topLevelWindow
= static_cast<nsIDOMWindowInternal
*>(this);
7350 // This is a workaround for the following problem:
7351 // When a window with an open sheet loses focus, only the sheet window
7352 // receives the NS_DEACTIVATE event. However, it's not the sheet that
7353 // should lose the active styling, but the containing top level window.
7355 topLevelWidget
->GetClientData(clientData
); // clientData is nsXULWindow
7356 nsISupports
* data
= static_cast<nsISupports
*>(clientData
);
7357 nsCOMPtr
<nsIInterfaceRequestor
> req(do_QueryInterface(data
));
7358 topLevelWindow
= do_GetInterface(req
);
7360 if (topLevelWindow
) {
7361 nsCOMPtr
<nsPIDOMWindow
> piWin(do_QueryInterface(topLevelWindow
));
7362 piWin
->SetActive(aActivate
);
7367 NotifyDocumentTree(nsIDocument
* aDocument
, void* aData
)
7369 aDocument
->EnumerateSubDocuments(NotifyDocumentTree
, nsnull
);
7370 aDocument
->DocumentStatesChanged(NS_DOCUMENT_STATE_WINDOW_INACTIVE
);
7375 nsGlobalWindow::SetActive(PRBool aActive
)
7377 nsPIDOMWindow::SetActive(aActive
);
7378 NotifyDocumentTree(mDoc
, nsnull
);
7381 void nsGlobalWindow::MaybeUpdateTouchState()
7383 FORWARD_TO_INNER_VOID(MaybeUpdateTouchState
, ());
7385 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
7387 nsCOMPtr
<nsIDOMWindow
> focusedWindow
;
7388 fm
->GetFocusedWindow(getter_AddRefs(focusedWindow
));
7390 if(this == focusedWindow
) {
7395 void nsGlobalWindow::UpdateTouchState()
7397 FORWARD_TO_INNER_VOID(UpdateTouchState
, ());
7399 nsCOMPtr
<nsIWidget
> mainWidget
= GetMainWidget();
7403 if (mMayHaveTouchEventListener
) {
7404 mainWidget
->RegisterTouchWindow();
7406 mainWidget
->UnregisterTouchWindow();
7412 nsGlobalWindow::EnableAccelerationUpdates()
7414 if (mHasAcceleration
) {
7415 nsCOMPtr
<nsIAccelerometer
> ac
=
7416 do_GetService(NS_ACCELEROMETER_CONTRACTID
);
7418 ac
->AddWindowListener(this);
7424 nsGlobalWindow::DisableAccelerationUpdates()
7426 if (mHasAcceleration
) {
7427 nsCOMPtr
<nsIAccelerometer
> ac
=
7428 do_GetService(NS_ACCELEROMETER_CONTRACTID
);
7430 ac
->RemoveWindowListener(this);
7436 nsGlobalWindow::SetChromeEventHandler(nsPIDOMEventTarget
* aChromeEventHandler
)
7438 SetChromeEventHandlerInternal(aChromeEventHandler
);
7439 if (IsOuterWindow()) {
7440 // update the chrome event handler on all our inner windows
7441 for (nsGlobalWindow
*inner
= (nsGlobalWindow
*)PR_LIST_HEAD(this);
7443 inner
= (nsGlobalWindow
*)PR_NEXT_LINK(inner
)) {
7444 NS_ASSERTION(!inner
->mOuterWindow
|| inner
->mOuterWindow
== this,
7445 "bad outer window pointer");
7446 inner
->SetChromeEventHandlerInternal(aChromeEventHandler
);
7448 } else if (mOuterWindow
) {
7449 // Need the cast to be able to call the protected method on a
7450 // superclass. We could make the method public instead, but it's really
7452 static_cast<nsGlobalWindow
*>(mOuterWindow
.get())->
7453 SetChromeEventHandlerInternal(aChromeEventHandler
);
7457 static PRBool
IsLink(nsIContent
* aContent
)
7459 nsCOMPtr
<nsIDOMHTMLAnchorElement
> anchor
= do_QueryInterface(aContent
);
7460 return (anchor
|| (aContent
&&
7461 aContent
->AttrValueIs(kNameSpaceID_XLink
, nsGkAtoms::type
,
7462 nsGkAtoms::simple
, eCaseMatters
)));
7466 nsGlobalWindow::SetFocusedNode(nsIContent
* aNode
,
7467 PRUint32 aFocusMethod
,
7470 FORWARD_TO_INNER_VOID(SetFocusedNode
, (aNode
, aFocusMethod
, aNeedsFocus
));
7472 NS_ASSERTION(!aNode
|| aNode
->GetCurrentDoc() == mDoc
,
7473 "setting focus to a node from the wrong document");
7475 if (mFocusedNode
!= aNode
) {
7476 UpdateCanvasFocus(PR_FALSE
, aNode
);
7477 mFocusedNode
= aNode
;
7478 mFocusMethod
= aFocusMethod
& FOCUSMETHOD_MASK
;
7479 mShowFocusRingForContent
= PR_FALSE
;
7483 // if a node was focused by a keypress, turn on focus rings for the
7485 if (mFocusMethod
& nsIFocusManager::FLAG_BYKEY
) {
7486 mFocusByKeyOccurred
= PR_TRUE
;
7488 // otherwise, we set mShowFocusRingForContent, as we don't want this to
7489 // be permanent for the window. On Windows, focus rings are only shown
7490 // when the FLAG_SHOWRING flag is used. On other platforms, focus rings
7491 // are only hidden for clicks on links.
7493 !(mFocusMethod
& nsIFocusManager::FLAG_BYMOUSE
) || !IsLink(aNode
) ||
7495 aFocusMethod
& nsIFocusManager::FLAG_SHOWRING
) {
7496 mShowFocusRingForContent
= PR_TRUE
;
7501 mNeedsFocus
= aNeedsFocus
;
7505 nsGlobalWindow::GetFocusMethod()
7507 FORWARD_TO_INNER(GetFocusMethod
, (), 0);
7509 return mFocusMethod
;
7513 nsGlobalWindow::ShouldShowFocusRing()
7515 FORWARD_TO_INNER(ShouldShowFocusRing
, (), PR_FALSE
);
7517 return mShowFocusRings
|| mShowFocusRingForContent
|| mFocusByKeyOccurred
;
7521 nsGlobalWindow::SetKeyboardIndicators(UIStateChangeType aShowAccelerators
,
7522 UIStateChangeType aShowFocusRings
)
7524 FORWARD_TO_INNER_VOID(SetKeyboardIndicators
, (aShowAccelerators
, aShowFocusRings
));
7526 // only change the flags that have been modified
7527 if (aShowAccelerators
!= UIStateChangeType_NoChange
)
7528 mShowAccelerators
= aShowAccelerators
== UIStateChangeType_Set
;
7529 if (aShowFocusRings
!= UIStateChangeType_NoChange
)
7530 mShowFocusRings
= aShowFocusRings
== UIStateChangeType_Set
;
7532 // propagate the indicators to child windows
7533 nsCOMPtr
<nsIDocShellTreeNode
> node
= do_QueryInterface(GetDocShell());
7535 PRInt32 childCount
= 0;
7536 node
->GetChildCount(&childCount
);
7538 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
7539 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
7540 node
->GetChildAt(i
, getter_AddRefs(childShell
));
7541 nsCOMPtr
<nsPIDOMWindow
> childWindow
= do_GetInterface(childShell
);
7543 childWindow
->SetKeyboardIndicators(aShowAccelerators
, aShowFocusRings
);
7549 // send content state notifications
7550 nsCOMPtr
<nsPresContext
> presContext
;
7552 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
7554 presContext
->EventStateManager()->
7555 SetContentState(mFocusedNode
, NS_EVENT_STATE_FOCUS
);
7562 nsGlobalWindow::GetKeyboardIndicators(PRBool
* aShowAccelerators
,
7563 PRBool
* aShowFocusRings
)
7565 FORWARD_TO_INNER_VOID(GetKeyboardIndicators
, (aShowAccelerators
, aShowFocusRings
));
7567 *aShowAccelerators
= mShowAccelerators
;
7568 *aShowFocusRings
= mShowFocusRings
;
7572 nsGlobalWindow::TakeFocus(PRBool aFocus
, PRUint32 aFocusMethod
)
7574 FORWARD_TO_INNER(TakeFocus
, (aFocus
, aFocusMethod
), PR_FALSE
);
7577 mFocusMethod
= aFocusMethod
& FOCUSMETHOD_MASK
;
7579 if (mHasFocus
!= aFocus
) {
7581 UpdateCanvasFocus(PR_TRUE
, mFocusedNode
);
7584 // if mNeedsFocus is true, then the document has not yet received a
7585 // document-level focus event. If there is a root content node, then return
7586 // true to tell the calling focus manager that a focus event is expected. If
7587 // there is no root content node, the document hasn't loaded enough yet, or
7588 // there isn't one and there is no point in firing a focus event.
7589 if (aFocus
&& mNeedsFocus
&& mDoc
&& mDoc
->GetRootElement() != nsnull
) {
7590 mNeedsFocus
= PR_FALSE
;
7594 mNeedsFocus
= PR_FALSE
;
7599 nsGlobalWindow::SetReadyForFocus()
7601 FORWARD_TO_INNER_VOID(SetReadyForFocus
, ());
7603 PRBool oldNeedsFocus
= mNeedsFocus
;
7604 mNeedsFocus
= PR_FALSE
;
7606 // update whether focus rings need to be shown using the state from the
7608 nsPIDOMWindow
* root
= GetPrivateRoot();
7610 PRBool showAccelerators
, showFocusRings
;
7611 root
->GetKeyboardIndicators(&showAccelerators
, &showFocusRings
);
7612 mShowFocusRings
= showFocusRings
;
7615 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
7617 fm
->WindowShown(this, oldNeedsFocus
);
7621 nsGlobalWindow::PageHidden()
7623 FORWARD_TO_INNER_VOID(PageHidden
, ());
7625 // the window is being hidden, so tell the focus manager that the frame is
7626 // no longer valid. Use the persisted field to determine if the document
7627 // is being destroyed.
7629 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
7631 fm
->WindowHidden(this);
7633 mNeedsFocus
= PR_TRUE
;
7637 nsGlobalWindow::DispatchAsyncHashchange()
7639 FORWARD_TO_INNER(DispatchAsyncHashchange
, (), NS_OK
);
7641 nsCOMPtr
<nsIRunnable
> event
=
7642 NS_NewRunnableMethod(this, &nsGlobalWindow::FireHashchange
);
7644 return NS_DispatchToCurrentThread(event
);
7648 nsGlobalWindow::FireHashchange()
7650 NS_ENSURE_TRUE(IsInnerWindow(), NS_ERROR_FAILURE
);
7652 // Don't do anything if the window is frozen.
7656 // Dispatch the hashchange event, which doesn't bubble and isn't cancelable,
7657 // to the outer window.
7658 return nsContentUtils::DispatchTrustedEvent(mDoc
, GetOuterWindow(),
7659 NS_LITERAL_STRING("hashchange"),
7660 PR_FALSE
, PR_FALSE
);
7664 nsGlobalWindow::DispatchSyncPopState()
7666 FORWARD_TO_INNER(DispatchSyncPopState
, (), NS_OK
);
7668 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
7669 "Must be safe to run script here.");
7671 // Check that PopState hasn't been pref'ed off.
7672 if (!nsContentUtils::GetBoolPref(sPopStatePrefStr
, PR_FALSE
))
7675 nsresult rv
= NS_OK
;
7677 // Bail if the window is frozen.
7682 // Bail if there's no document or the document's readystate isn't "complete".
7687 nsIDocument::ReadyState readyState
= mDoc
->GetReadyStateEnum();
7688 if (readyState
!= nsIDocument::READYSTATE_COMPLETE
) {
7692 // Get the document's pending state object -- it contains the data we're
7693 // going to send along with the popstate event. The object is serialized as
7695 nsAString
& stateObjJSON
= mDoc
->GetPendingStateObject();
7697 nsCOMPtr
<nsIVariant
> stateObj
;
7698 // Parse the JSON, if there's any to parse.
7699 if (!stateObjJSON
.IsEmpty()) {
7700 // Get the JSContext associated with our document. We need this for
7702 nsCOMPtr
<nsIDocument
> document
= do_QueryInterface(mDocument
);
7703 NS_ENSURE_TRUE(document
, NS_ERROR_FAILURE
);
7705 // Get the JSContext from the document, like we do in
7706 // nsContentUtils::GetContextFromDocument().
7707 nsIScriptGlobalObject
*sgo
= document
->GetScopeObject();
7708 NS_ENSURE_TRUE(sgo
, NS_ERROR_FAILURE
);
7710 nsIScriptContext
*scx
= sgo
->GetContext();
7711 NS_ENSURE_TRUE(scx
, NS_ERROR_FAILURE
);
7713 JSContext
*cx
= (JSContext
*) scx
->GetNativeContext();
7715 // Make sure we in the request while we have jsval on the native stack.
7716 JSAutoRequest
ar(cx
);
7718 // If our json call triggers a JS-to-C++ call, we want that call to use cx
7719 // as the context. So we push cx onto the context stack.
7720 nsCxPusher cxPusher
;
7722 jsval jsStateObj
= JSVAL_NULL
;
7724 // Deserialize the state object into an nsIVariant.
7725 nsCOMPtr
<nsIJSON
> json
= do_GetService("@mozilla.org/dom/json;1");
7726 NS_ENSURE_TRUE(cxPusher
.Push(cx
), NS_ERROR_FAILURE
);
7727 rv
= json
->DecodeToJSVal(stateObjJSON
, cx
, &jsStateObj
);
7728 NS_ENSURE_SUCCESS(rv
, rv
);
7731 nsCOMPtr
<nsIXPConnect
> xpconnect
= do_GetService(nsIXPConnect::GetCID());
7732 NS_ENSURE_TRUE(xpconnect
, NS_ERROR_FAILURE
);
7733 rv
= xpconnect
->JSValToVariant(cx
, &jsStateObj
, getter_AddRefs(stateObj
));
7734 NS_ENSURE_SUCCESS(rv
, rv
);
7737 // Obtain a presentation shell for use in creating a popstate event.
7738 nsIPresShell
*shell
= mDoc
->GetShell();
7739 nsRefPtr
<nsPresContext
> presContext
;
7741 presContext
= shell
->GetPresContext();
7744 // Create a new popstate event
7745 nsCOMPtr
<nsIDOMEvent
> domEvent
;
7746 rv
= nsEventDispatcher::CreateEvent(presContext
, nsnull
,
7747 NS_LITERAL_STRING("popstateevent"),
7748 getter_AddRefs(domEvent
));
7749 NS_ENSURE_SUCCESS(rv
, rv
);
7751 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent
= do_QueryInterface(domEvent
);
7752 NS_ENSURE_TRUE(privateEvent
, NS_ERROR_FAILURE
);
7754 // Initialize the popstate event, which does bubble but isn't cancellable.
7755 nsCOMPtr
<nsIDOMPopStateEvent
> popstateEvent
= do_QueryInterface(domEvent
);
7756 rv
= popstateEvent
->InitPopStateEvent(NS_LITERAL_STRING("popstate"),
7759 NS_ENSURE_SUCCESS(rv
, rv
);
7761 rv
= privateEvent
->SetTrusted(PR_TRUE
);
7762 NS_ENSURE_SUCCESS(rv
, rv
);
7764 nsCOMPtr
<nsIDOMEventTarget
> outerWindow
=
7765 do_QueryInterface(GetOuterWindow());
7766 NS_ENSURE_TRUE(outerWindow
, NS_ERROR_UNEXPECTED
);
7768 rv
= privateEvent
->SetTarget(outerWindow
);
7769 NS_ENSURE_SUCCESS(rv
, rv
);
7771 PRBool dummy
; // default action
7772 return DispatchEvent(popstateEvent
, &dummy
);
7775 // Find an nsICanvasFrame under aFrame. Only search the principal
7776 // child lists. aFrame must be non-null.
7777 static nsCanvasFrame
* FindCanvasFrame(nsIFrame
* aFrame
)
7779 nsCanvasFrame
* canvasFrame
= do_QueryFrame(aFrame
);
7784 nsIFrame
* kid
= aFrame
->GetFirstChild(nsnull
);
7786 canvasFrame
= FindCanvasFrame(kid
);
7790 kid
= kid
->GetNextSibling();
7796 //-------------------------------------------------------
7797 // Tells the HTMLFrame/CanvasFrame that is now has focus
7799 nsGlobalWindow::UpdateCanvasFocus(PRBool aFocusChanged
, nsIContent
* aNewContent
)
7801 // this is called from the inner window so use GetDocShell
7802 nsIDocShell
* docShell
= GetDocShell();
7806 nsCOMPtr
<nsIEditorDocShell
> editorDocShell
= do_QueryInterface(docShell
);
7807 if (editorDocShell
) {
7809 editorDocShell
->GetEditable(&editable
);
7814 nsCOMPtr
<nsIPresShell
> presShell
;
7815 docShell
->GetPresShell(getter_AddRefs(presShell
));
7816 if (!presShell
|| !mDocument
)
7819 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
7820 Element
*rootElement
= doc
->GetRootElement();
7822 if ((mHasFocus
|| aFocusChanged
) &&
7823 (mFocusedNode
== rootElement
|| aNewContent
== rootElement
)) {
7824 nsIFrame
* frame
= rootElement
->GetPrimaryFrame();
7826 frame
= frame
->GetParent();
7827 nsCanvasFrame
* canvasFrame
= do_QueryFrame(frame
);
7829 canvasFrame
->SetHasFocus(mHasFocus
&& rootElement
== aNewContent
);
7834 // Look for the frame the hard way
7835 nsIFrame
* frame
= presShell
->GetRootFrame();
7837 nsCanvasFrame
* canvasFrame
= FindCanvasFrame(frame
);
7839 canvasFrame
->SetHasFocus(PR_FALSE
);
7845 //*****************************************************************************
7846 // nsGlobalWindow::nsIDOMViewCSS
7847 //*****************************************************************************
7850 nsGlobalWindow::GetComputedStyle(nsIDOMElement
* aElt
,
7851 const nsAString
& aPseudoElt
,
7852 nsIDOMCSSStyleDeclaration
** aReturn
)
7854 FORWARD_TO_OUTER(GetComputedStyle
, (aElt
, aPseudoElt
, aReturn
),
7855 NS_ERROR_NOT_INITIALIZED
);
7857 NS_ENSURE_ARG_POINTER(aReturn
);
7861 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
7868 nsCOMPtr
<nsIPresShell
> presShell
;
7869 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
7875 nsRefPtr
<nsComputedDOMStyle
> compStyle
;
7876 nsresult rv
= NS_NewComputedDOMStyle(aElt
, aPseudoElt
, presShell
,
7877 getter_AddRefs(compStyle
));
7878 NS_ENSURE_SUCCESS(rv
, rv
);
7880 *aReturn
= compStyle
.forget().get();
7885 //*****************************************************************************
7886 // nsGlobalWindow::nsIDOMAbstractView
7887 //*****************************************************************************
7890 nsGlobalWindow::GetDocument(nsIDOMDocumentView
** aDocumentView
)
7892 NS_ENSURE_ARG_POINTER(aDocumentView
);
7894 nsresult rv
= NS_OK
;
7897 rv
= CallQueryInterface(mDocument
, aDocumentView
);
7900 *aDocumentView
= nsnull
;
7906 //*****************************************************************************
7907 // nsGlobalWindow::nsIDOMStorageWindow
7908 //*****************************************************************************
7911 nsGlobalWindow::GetSessionStorage(nsIDOMStorage
** aSessionStorage
)
7913 FORWARD_TO_INNER(GetSessionStorage
, (aSessionStorage
), NS_ERROR_UNEXPECTED
);
7915 nsIPrincipal
*principal
= GetPrincipal();
7916 nsIDocShell
* docShell
= GetDocShell();
7918 if (!principal
|| !docShell
) {
7919 *aSessionStorage
= nsnull
;
7923 if (!nsContentUtils::GetBoolPref(kStorageEnabled
)) {
7924 *aSessionStorage
= nsnull
;
7928 if (mSessionStorage
) {
7930 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
7931 PR_LogPrint("nsGlobalWindow %p has %p sessionStorage", this, mSessionStorage
.get());
7934 nsCOMPtr
<nsPIDOMStorage
> piStorage
= do_QueryInterface(mSessionStorage
);
7936 PRBool canAccess
= piStorage
->CanAccess(principal
);
7937 NS_ASSERTION(canAccess
,
7938 "window %x owned sessionStorage "
7939 "that could not be accessed!");
7941 mSessionStorage
= nsnull
;
7946 if (!mSessionStorage
) {
7947 *aSessionStorage
= nsnull
;
7949 nsString documentURI
;
7950 nsCOMPtr
<nsIDOM3Document
> document3
= do_QueryInterface(mDoc
);
7952 document3
->GetDocumentURI(documentURI
);
7954 nsresult rv
= docShell
->GetSessionStorageForPrincipal(principal
,
7957 getter_AddRefs(mSessionStorage
));
7958 NS_ENSURE_SUCCESS(rv
, rv
);
7961 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
7962 PR_LogPrint("nsGlobalWindow %p tried to get a new sessionStorage %p", this, mSessionStorage
.get());
7966 if (!mSessionStorage
) {
7967 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
7972 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
7973 PR_LogPrint("nsGlobalWindow %p returns %p sessionStorage", this, mSessionStorage
.get());
7977 NS_ADDREF(*aSessionStorage
= mSessionStorage
);
7982 nsGlobalWindow::GetGlobalStorage(nsIDOMStorageList
** aGlobalStorage
)
7984 NS_ENSURE_ARG_POINTER(aGlobalStorage
);
7987 if (!nsContentUtils::GetBoolPref(kStorageEnabled
)) {
7988 *aGlobalStorage
= nsnull
;
7992 if (!sGlobalStorageList
) {
7993 nsresult rv
= NS_NewDOMStorageList(&sGlobalStorageList
);
7994 NS_ENSURE_SUCCESS(rv
, rv
);
7997 *aGlobalStorage
= sGlobalStorageList
;
7998 NS_IF_ADDREF(*aGlobalStorage
);
8002 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
8007 nsGlobalWindow::GetLocalStorage(nsIDOMStorage
** aLocalStorage
)
8009 FORWARD_TO_INNER(GetLocalStorage
, (aLocalStorage
), NS_ERROR_UNEXPECTED
);
8011 NS_ENSURE_ARG(aLocalStorage
);
8013 if (!nsContentUtils::GetBoolPref(kStorageEnabled
)) {
8014 *aLocalStorage
= nsnull
;
8018 if (!mLocalStorage
) {
8019 *aLocalStorage
= nsnull
;
8023 PRPackedBool unused
;
8024 if (!nsDOMStorage::CanUseStorage(&unused
))
8025 return NS_ERROR_DOM_SECURITY_ERR
;
8027 nsIPrincipal
*principal
= GetPrincipal();
8031 nsCOMPtr
<nsIDOMStorageManager
> storageManager
=
8032 do_GetService("@mozilla.org/dom/storagemanager;1", &rv
);
8033 NS_ENSURE_SUCCESS(rv
, rv
);
8035 nsString documentURI
;
8036 nsCOMPtr
<nsIDOM3Document
> document3
= do_QueryInterface(mDoc
);
8038 document3
->GetDocumentURI(documentURI
);
8040 rv
= storageManager
->GetLocalStorageForPrincipal(principal
,
8042 getter_AddRefs(mLocalStorage
));
8043 NS_ENSURE_SUCCESS(rv
, rv
);
8046 NS_ADDREF(*aLocalStorage
= mLocalStorage
);
8050 //*****************************************************************************
8051 // nsGlobalWindow::nsIDOMStorageIndexedDB
8052 //*****************************************************************************
8055 nsGlobalWindow::GetMozIndexedDB(nsIIDBFactory
** _retval
)
8058 nsCOMPtr
<mozIThirdPartyUtil
> thirdPartyUtil
=
8059 do_GetService(THIRDPARTYUTIL_CONTRACTID
);
8060 NS_ENSURE_TRUE(thirdPartyUtil
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
8062 PRBool isThirdParty
;
8063 nsresult rv
= thirdPartyUtil
->IsThirdPartyWindow(this, nsnull
,
8065 NS_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
8068 NS_WARNING("IndexedDB is not permitted in a third-party window.");
8073 mIndexedDB
= indexedDB::IDBFactory::Create(this);
8074 NS_ENSURE_TRUE(mIndexedDB
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
8077 nsCOMPtr
<nsIIDBFactory
> request(mIndexedDB
);
8078 request
.forget(_retval
);
8082 //*****************************************************************************
8083 // nsGlobalWindow::nsIInterfaceRequestor
8084 //*****************************************************************************
8087 nsGlobalWindow::GetInterface(const nsIID
& aIID
, void **aSink
)
8089 NS_ENSURE_ARG_POINTER(aSink
);
8092 if (aIID
.Equals(NS_GET_IID(nsIDocCharset
))) {
8093 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
8096 nsCOMPtr
<nsIDocCharset
> docCharset(do_QueryInterface(mDocShell
));
8098 *aSink
= docCharset
;
8099 NS_ADDREF(((nsISupports
*) *aSink
));
8103 else if (aIID
.Equals(NS_GET_IID(nsIWebNavigation
))) {
8104 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
8107 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
8110 NS_ADDREF(((nsISupports
*) *aSink
));
8115 else if (aIID
.Equals(NS_GET_IID(nsIWebBrowserPrint
))) {
8116 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
8119 nsCOMPtr
<nsIContentViewer
> viewer
;
8120 mDocShell
->GetContentViewer(getter_AddRefs(viewer
));
8122 nsCOMPtr
<nsIWebBrowserPrint
> webBrowserPrint(do_QueryInterface(viewer
));
8123 if (webBrowserPrint
) {
8124 *aSink
= webBrowserPrint
;
8125 NS_ADDREF(((nsISupports
*) *aSink
));
8131 else if (aIID
.Equals(NS_GET_IID(nsIScriptEventManager
))) {
8133 nsIScriptEventManager
* mgr
= mDoc
->GetScriptEventManager();
8136 NS_ADDREF(((nsISupports
*) *aSink
));
8140 else if (aIID
.Equals(NS_GET_IID(nsIDOMWindowUtils
)) ||
8141 aIID
.Equals(NS_GET_IID(nsIDOMWindowUtils_MOZILLA_2_0_BRANCH
))) {
8142 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
8144 nsCOMPtr
<nsISupports
> utils(do_QueryReferent(mWindowUtils
));
8147 NS_ADDREF(((nsISupports
*) *aSink
));
8149 nsDOMWindowUtils
*utilObj
= new nsDOMWindowUtils(this);
8150 nsCOMPtr
<nsISupports
> utilsIfc
=
8151 NS_ISUPPORTS_CAST(nsIDOMWindowUtils
*, utilObj
);
8153 mWindowUtils
= do_GetWeakReference(utilsIfc
);
8155 NS_ADDREF(((nsISupports
*) *aSink
));
8160 return QueryInterface(aIID
, aSink
);
8163 return *aSink
? NS_OK
: NS_ERROR_NO_INTERFACE
;
8167 nsGlobalWindow::FireOfflineStatusEvent()
8172 if (NS_IsOffline()) {
8173 name
.AssignLiteral("offline");
8175 name
.AssignLiteral("online");
8177 // The event is fired at the body element, or if there is no body element,
8179 nsCOMPtr
<nsISupports
> eventTarget
= mDoc
.get();
8180 nsCOMPtr
<nsIDOMHTMLDocument
> htmlDoc
= do_QueryInterface(mDoc
);
8182 nsCOMPtr
<nsIDOMHTMLElement
> body
;
8183 htmlDoc
->GetBody(getter_AddRefs(body
));
8189 nsCOMPtr
<nsIDOMElement
> documentElement
;
8190 mDocument
->GetDocumentElement(getter_AddRefs(documentElement
));
8191 if(documentElement
) {
8192 eventTarget
= documentElement
;
8195 nsContentUtils::DispatchTrustedEvent(mDoc
, eventTarget
, name
, PR_TRUE
, PR_FALSE
);
8199 nsGlobalWindow::Observe(nsISupports
* aSubject
, const char* aTopic
,
8200 const PRUnichar
* aData
)
8202 if (!nsCRT::strcmp(aTopic
, NS_IOSERVICE_OFFLINE_STATUS_TOPIC
)) {
8204 // if an even number of notifications arrive while we're frozen,
8205 // we don't need to fire.
8206 mFireOfflineStatusChangeEventOnThaw
= !mFireOfflineStatusChangeEventOnThaw
;
8208 FireOfflineStatusEvent();
8213 if (IsInnerWindow() && !nsCRT::strcmp(aTopic
, "dom-storage-changed")) {
8214 nsIPrincipal
*principal
;
8217 principal
= GetPrincipal();
8219 // A global storage object changed, check to see if it's one
8220 // this window can access.
8222 nsCOMPtr
<nsIURI
> codebase
;
8223 principal
->GetURI(getter_AddRefs(codebase
));
8229 nsCAutoString currentDomain
;
8230 rv
= codebase
->GetAsciiHost(currentDomain
);
8231 if (NS_FAILED(rv
)) {
8235 if (!nsDOMStorageList::CanAccessDomain(NS_ConvertUTF16toUTF8(aData
),
8237 // This window can't reach the global storage object for the
8238 // domain for which the change happened, so don't fire any
8239 // events in this window.
8245 nsAutoString
domain(aData
);
8248 // This window is frozen, rather than firing the events here,
8249 // store the domain in which the change happened and fire the
8250 // events if we're ever thawed.
8252 if (!mPendingStorageEventsObsolete
) {
8253 mPendingStorageEventsObsolete
= new nsDataHashtable
<nsStringHashKey
, PRBool
>;
8254 NS_ENSURE_TRUE(mPendingStorageEventsObsolete
, NS_ERROR_OUT_OF_MEMORY
);
8256 rv
= mPendingStorageEventsObsolete
->Init();
8257 NS_ENSURE_SUCCESS(rv
, rv
);
8260 mPendingStorageEventsObsolete
->Put(domain
, PR_TRUE
);
8265 nsRefPtr
<nsDOMStorageEventObsolete
> event
= new nsDOMStorageEventObsolete();
8266 NS_ENSURE_TRUE(event
, NS_ERROR_OUT_OF_MEMORY
);
8268 rv
= event
->InitStorageEvent(NS_LITERAL_STRING("storage"), PR_FALSE
, PR_FALSE
, domain
);
8269 NS_ENSURE_SUCCESS(rv
, rv
);
8271 nsCOMPtr
<nsIDOMHTMLDocument
> htmlDoc(do_QueryInterface(mDocument
));
8273 nsCOMPtr
<nsIDOMEventTarget
> target
;
8276 nsCOMPtr
<nsIDOMHTMLElement
> body
;
8277 htmlDoc
->GetBody(getter_AddRefs(body
));
8279 target
= do_QueryInterface(body
);
8286 PRBool defaultActionEnabled
;
8287 target
->DispatchEvent((nsIDOMStorageEventObsolete
*)event
, &defaultActionEnabled
);
8292 if (IsInnerWindow() && !nsCRT::strcmp(aTopic
, "dom-storage2-changed")) {
8293 nsIPrincipal
*principal
;
8296 nsCOMPtr
<nsIDOMStorageEvent
> event
= do_QueryInterface(aSubject
, &rv
);
8297 NS_ENSURE_SUCCESS(rv
, rv
);
8299 nsCOMPtr
<nsIDOMStorage
> changingStorage
;
8300 rv
= event
->GetStorageArea(getter_AddRefs(changingStorage
));
8301 NS_ENSURE_SUCCESS(rv
, rv
);
8303 nsCOMPtr
<nsPIDOMStorage
> pistorage
= do_QueryInterface(changingStorage
);
8304 nsPIDOMStorage::nsDOMStorageType storageType
= pistorage
->StorageType();
8306 principal
= GetPrincipal();
8307 switch (storageType
)
8309 case nsPIDOMStorage::SessionStorage
:
8311 if (SameCOMIdentity(mSessionStorage
, changingStorage
)) {
8312 // Do not fire any events for the same storage object, it's not shared
8313 // among windows, see nsGlobalWindow::GetSessionStoarge()
8317 nsCOMPtr
<nsIDOMStorage
> storage
= mSessionStorage
;
8319 nsIDocShell
* docShell
= GetDocShell();
8320 if (principal
&& docShell
) {
8321 // No need to pass documentURI here, it's only needed when we want
8322 // to create a new storage, the third paramater would be PR_TRUE
8323 docShell
->GetSessionStorageForPrincipal(principal
,
8326 getter_AddRefs(storage
));
8330 if (!pistorage
->IsForkOf(storage
)) {
8331 // This storage event is coming from a different doc shell,
8332 // i.e. it is a clone, ignore this event.
8337 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
8338 PR_LogPrint("nsGlobalWindow %p with sessionStorage %p passing event from %p", this, mSessionStorage
.get(), pistorage
.get());
8344 case nsPIDOMStorage::LocalStorage
:
8346 if (SameCOMIdentity(mLocalStorage
, changingStorage
)) {
8347 // Do not fire any events for the same storage object, it's not shared
8348 // among windows, see nsGlobalWindow::GetLocalStoarge()
8352 // Allow event fire only for the same principal storages
8353 // XXX We have to use EqualsIgnoreDomain after bug 495337 lands
8354 nsIPrincipal
*storagePrincipal
= pistorage
->Principal();
8357 rv
= storagePrincipal
->Equals(principal
, &equals
);
8358 NS_ENSURE_SUCCESS(rv
, rv
);
8370 // This window is frozen, rather than firing the events here,
8371 // store the domain in which the change happened and fire the
8372 // events if we're ever thawed.
8374 mPendingStorageEvents
.AppendObject(event
);
8378 PRBool defaultActionEnabled
;
8379 DispatchEvent((nsIDOMStorageEvent
*)event
, &defaultActionEnabled
);
8384 if (!nsCRT::strcmp(aTopic
, "offline-cache-update-added")) {
8385 if (mApplicationCache
)
8388 // Instantiate the application object now. It observes update belonging to
8389 // this window's document and correctly updates the applicationCache object
8391 nsCOMPtr
<nsIDOMOfflineResourceList
> applicationCache
;
8392 GetApplicationCache(getter_AddRefs(applicationCache
));
8393 nsCOMPtr
<nsIObserver
> observer
= do_QueryInterface(applicationCache
);
8395 observer
->Observe(aSubject
, aTopic
, aData
);
8400 NS_WARNING("unrecognized topic in nsGlobalWindow::Observe");
8401 return NS_ERROR_FAILURE
;
8404 static PLDHashOperator
8405 FirePendingStorageEvents(const nsAString
& aKey
, PRBool aData
, void *userArg
)
8407 nsGlobalWindow
*win
= static_cast<nsGlobalWindow
*>(userArg
);
8409 nsCOMPtr
<nsIDOMStorage
> storage
;
8410 win
->GetSessionStorage(getter_AddRefs(storage
));
8413 win
->Observe(storage
, "dom-storage-changed",
8414 aKey
.IsEmpty() ? nsnull
: PromiseFlatString(aKey
).get());
8417 return PL_DHASH_NEXT
;
8421 nsGlobalWindow::FireDelayedDOMEvents()
8423 FORWARD_TO_INNER(FireDelayedDOMEvents
, (), NS_ERROR_UNEXPECTED
);
8425 for (PRInt32 i
= 0; i
< mPendingStorageEvents
.Count(); ++i
) {
8426 Observe(mPendingStorageEvents
[i
], "dom-storage2-changed", nsnull
);
8429 if (mPendingStorageEventsObsolete
) {
8430 // Fire pending storage events.
8431 mPendingStorageEventsObsolete
->EnumerateRead(FirePendingStorageEvents
, this);
8433 delete mPendingStorageEventsObsolete
;
8434 mPendingStorageEventsObsolete
= nsnull
;
8437 if (mApplicationCache
) {
8438 static_cast<nsDOMOfflineResourceList
*>(mApplicationCache
.get())->FirePendingEvents();
8441 if (mFireOfflineStatusChangeEventOnThaw
) {
8442 mFireOfflineStatusChangeEventOnThaw
= PR_FALSE
;
8443 FireOfflineStatusEvent();
8446 nsCOMPtr
<nsIDocShellTreeNode
> node
=
8447 do_QueryInterface(GetDocShell());
8449 PRInt32 childCount
= 0;
8450 node
->GetChildCount(&childCount
);
8452 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
8453 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
8454 node
->GetChildAt(i
, getter_AddRefs(childShell
));
8455 NS_ASSERTION(childShell
, "null child shell");
8457 nsCOMPtr
<nsPIDOMWindow
> pWin
= do_GetInterface(childShell
);
8459 nsGlobalWindow
*win
=
8460 static_cast<nsGlobalWindow
*>
8461 (static_cast<nsPIDOMWindow
*>(pWin
));
8462 win
->FireDelayedDOMEvents();
8470 //*****************************************************************************
8471 // nsGlobalWindow: Window Control Functions
8472 //*****************************************************************************
8474 nsIDOMWindowInternal
*
8475 nsGlobalWindow::GetParentInternal()
8477 FORWARD_TO_OUTER(GetParentInternal
, (), nsnull
);
8479 nsIDOMWindowInternal
*parentInternal
= nsnull
;
8481 nsCOMPtr
<nsIDOMWindow
> parent
;
8482 GetParent(getter_AddRefs(parent
));
8484 if (parent
&& parent
!= static_cast<nsIDOMWindow
*>(this)) {
8485 nsCOMPtr
<nsIDOMWindowInternal
> tmp(do_QueryInterface(parent
));
8486 NS_ASSERTION(parent
, "Huh, parent not an nsIDOMWindowInternal?");
8488 parentInternal
= tmp
;
8491 return parentInternal
;
8496 nsGlobalWindow::CloseBlockScriptTerminationFunc(nsISupports
*aRef
)
8498 nsGlobalWindow
* pwin
= static_cast<nsGlobalWindow
*>
8499 (static_cast<nsPIDOMWindow
*>(aRef
));
8500 pwin
->mBlockScriptedClosingFlag
= PR_FALSE
;
8504 nsGlobalWindow::OpenInternal(const nsAString
& aUrl
, const nsAString
& aName
,
8505 const nsAString
& aOptions
, PRBool aDialog
,
8506 PRBool aContentModal
, PRBool aCalledNoScript
,
8507 PRBool aDoJSFixups
, nsIArray
*argv
,
8508 nsISupports
*aExtraArgument
,
8509 nsIPrincipal
*aCalleePrincipal
,
8510 JSContext
*aJSCallerContext
,
8511 nsIDOMWindow
**aReturn
)
8513 FORWARD_TO_OUTER(OpenInternal
, (aUrl
, aName
, aOptions
, aDialog
,
8514 aContentModal
, aCalledNoScript
, aDoJSFixups
,
8515 argv
, aExtraArgument
, aCalleePrincipal
,
8516 aJSCallerContext
, aReturn
),
8517 NS_ERROR_NOT_INITIALIZED
);
8522 argv
->GetLength(&argc
);
8524 NS_PRECONDITION(!aExtraArgument
|| (!argv
&& argc
== 0),
8525 "Can't pass in arguments both ways");
8526 NS_PRECONDITION(!aCalledNoScript
|| (!argv
&& argc
== 0),
8527 "Can't pass JS args when called via the noscript methods");
8528 NS_PRECONDITION(!aJSCallerContext
|| !aCalledNoScript
,
8529 "Shouldn't have caller context when called noscript");
8533 nsCOMPtr
<nsIWebBrowserChrome
> chrome
;
8534 GetWebBrowserChrome(getter_AddRefs(chrome
));
8536 // No chrome means we don't want to go through with this open call
8537 // -- see nsIWindowWatcher.idl
8538 return NS_ERROR_NOT_AVAILABLE
;
8541 NS_ASSERTION(mDocShell
, "Must have docshell here");
8543 const PRBool checkForPopup
=
8544 !aDialog
&& !WindowExists(aName
, !aCalledNoScript
);
8546 // Note: it's very important that this be an nsXPIDLCString, since we want
8547 // .get() on it to return nsnull until we write stuff to it. The window
8548 // watcher expects a null URL string if there is no URL to load.
8550 nsresult rv
= NS_OK
;
8552 // It's important to do this security check before determining whether this
8553 // window opening should be blocked, to ensure that we don't FireAbuseEvents
8554 // for a window opening that wouldn't have succeeded in the first place.
8555 if (!aUrl
.IsEmpty()) {
8556 AppendUTF16toUTF8(aUrl
, url
);
8558 /* Check whether the URI is allowed, but not for dialogs --
8559 see bug 56851. The security of this function depends on
8560 window.openDialog being inaccessible from web scripts */
8561 if (url
.get() && !aDialog
)
8562 rv
= SecurityCheckURL(url
.get());
8568 PopupControlState abuseLevel
= gPopupControlState
;
8569 if (checkForPopup
) {
8570 abuseLevel
= RevisePopupAbuseLevel(abuseLevel
);
8571 if (abuseLevel
>= openAbused
) {
8572 if (aJSCallerContext
) {
8573 // If script in some other window is doing a window.open on us and
8574 // it's being blocked, then it's OK to close us afterwards, probably.
8575 // But if we're doing a window.open on ourselves and block the popup,
8576 // prevent this window from closing until after this script terminates
8577 // so that whatever popup blocker UI the app has will be visible.
8578 if (mContext
== GetScriptContextFromJSContext(aJSCallerContext
)) {
8579 mBlockScriptedClosingFlag
= PR_TRUE
;
8580 mContext
->SetTerminationFunction(CloseBlockScriptTerminationFunc
,
8581 static_cast<nsPIDOMWindow
*>
8586 FireAbuseEvents(PR_TRUE
, PR_FALSE
, aUrl
, aName
, aOptions
);
8587 return aDoJSFixups
? NS_OK
: NS_ERROR_FAILURE
;
8591 nsCOMPtr
<nsIDOMWindow
> domReturn
;
8593 nsCOMPtr
<nsIWindowWatcher
> wwatch
=
8594 do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &rv
);
8595 NS_ENSURE_TRUE(wwatch
, rv
);
8597 NS_ConvertUTF16toUTF8
options(aOptions
);
8598 NS_ConvertUTF16toUTF8
name(aName
);
8600 const char *options_ptr
= aOptions
.IsEmpty() ? nsnull
: options
.get();
8601 const char *name_ptr
= aName
.IsEmpty() ? nsnull
: name
.get();
8604 // Reset popup state while opening a window to prevent the
8605 // current state from being active the whole time a modal
8607 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
8609 if (!aCalledNoScript
) {
8610 nsCOMPtr
<nsPIWindowWatcher
> pwwatch(do_QueryInterface(wwatch
));
8611 NS_ASSERTION(pwwatch
,
8612 "Unable to open windows from JS because window watcher "
8614 NS_ENSURE_TRUE(pwwatch
, NS_ERROR_UNEXPECTED
);
8616 rv
= pwwatch
->OpenWindowJS(this, url
.get(), name_ptr
, options_ptr
,
8618 getter_AddRefs(domReturn
));
8620 // Push a null JSContext here so that the window watcher won't screw us
8621 // up. We do NOT want this case looking at the JS context on the stack
8622 // when searching. Compare comments on
8623 // nsIDOMWindowInternal::OpenWindow and nsIWindowWatcher::OpenWindow.
8624 nsCOMPtr
<nsIJSContextStack
> stack
;
8626 if (!aContentModal
) {
8627 stack
= do_GetService(sJSStackContractID
);
8631 rv
= stack
->Push(nsnull
);
8632 NS_ENSURE_SUCCESS(rv
, rv
);
8635 rv
= wwatch
->OpenWindow(this, url
.get(), name_ptr
, options_ptr
,
8636 aExtraArgument
, getter_AddRefs(domReturn
));
8641 NS_ASSERTION(!cx
, "Unexpected JSContext popped!");
8646 NS_ENSURE_SUCCESS(rv
, rv
);
8650 domReturn
.swap(*aReturn
);
8653 nsCOMPtr
<nsIDOMChromeWindow
> chrome_win(do_QueryInterface(*aReturn
));
8655 // A new non-chrome window was created from a call to
8656 // window.open() from JavaScript, make sure there's a document in
8657 // the new window. We do this by simply asking the new window for
8658 // its document, this will synchronously create an empty document
8659 // if there is no document in the window.
8660 // XXXbz should this just use EnsureInnerWindow()?
8663 nsCOMPtr
<nsPIDOMWindow
> pidomwin(do_QueryInterface(*aReturn
));
8665 nsIDOMDocument
*temp
= pidomwin
->GetExtantDocument();
8667 NS_ASSERTION(temp
, "No document in new window!!!");
8671 nsCOMPtr
<nsIDOMDocument
> doc
;
8672 (*aReturn
)->GetDocument(getter_AddRefs(doc
));
8676 if (checkForPopup
) {
8677 if (abuseLevel
>= openControlled
) {
8678 nsGlobalWindow
*opened
= static_cast<nsGlobalWindow
*>(*aReturn
);
8679 if (!opened
->IsPopupSpamWindow()) {
8680 opened
->SetPopupSpamWindow(PR_TRUE
);
8681 ++gOpenPopupSpamCount
;
8684 if (abuseLevel
>= openAbused
)
8685 FireAbuseEvents(PR_FALSE
, PR_TRUE
, aUrl
, aName
, aOptions
);
8693 nsGlobalWindow::CloseWindow(nsISupports
*aWindow
)
8695 nsCOMPtr
<nsPIDOMWindow
> win(do_QueryInterface(aWindow
));
8697 nsGlobalWindow
* globalWin
=
8698 static_cast<nsGlobalWindow
*>
8699 (static_cast<nsPIDOMWindow
*>(win
));
8701 // Need to post an event for closing, otherwise window and
8702 // presshell etc. may get destroyed while creating frames, bug 338897.
8703 nsCloseEvent::PostCloseEvent(globalWin
);
8704 // else if OOM, better not to close. That might cause a crash.
8709 nsGlobalWindow::ClearWindowScope(nsISupports
*aWindow
)
8711 nsCOMPtr
<nsIScriptGlobalObject
> sgo(do_QueryInterface(aWindow
));
8712 nsIScriptContext
*scx
= sgo
->GetContext();
8714 scx
->ClearScope(sgo
->GetGlobalJSObject(), PR_TRUE
);
8718 //*****************************************************************************
8719 // nsGlobalWindow: Timeout Functions
8720 //*****************************************************************************
8722 PRUint32 sNestingLevel
;
8725 nsGlobalWindow::SetTimeoutOrInterval(nsIScriptTimeoutHandler
*aHandler
,
8727 PRBool aIsInterval
, PRInt32
*aReturn
)
8729 FORWARD_TO_INNER(SetTimeoutOrInterval
, (aHandler
, interval
, aIsInterval
, aReturn
),
8730 NS_ERROR_NOT_INITIALIZED
);
8732 // If we don't have a document (we could have been unloaded since
8733 // the call to setTimeout was made), do nothing.
8738 PRUint32 nestingLevel
= sNestingLevel
+ 1;
8739 if (interval
< DOMMinTimeoutValue()) {
8740 if (aIsInterval
|| nestingLevel
>= DOM_CLAMP_TIMEOUT_NESTING_LEVEL
) {
8741 // Don't allow timeouts less than DOMMinTimeoutValue() from
8744 interval
= DOMMinTimeoutValue();;
8746 else if (interval
< 0) {
8747 // Clamp negative intervals to 0.
8753 NS_ASSERTION(interval
>= 0, "DOMMinTimeoutValue() lies");
8754 PRUint32 realInterval
= interval
;
8756 // Make sure we don't proceed with a interval larger than our timer
8758 if (realInterval
> PR_IntervalToMilliseconds(DOM_MAX_TIMEOUT_VALUE
)) {
8759 realInterval
= PR_IntervalToMilliseconds(DOM_MAX_TIMEOUT_VALUE
);
8762 nsTimeout
*timeout
= new nsTimeout();
8764 return NS_ERROR_OUT_OF_MEMORY
;
8766 // Increment the timeout's reference count to represent this function's hold
8771 timeout
->mInterval
= realInterval
;
8773 timeout
->mScriptHandler
= aHandler
;
8775 // Get principal of currently executing code, save for execution of timeout.
8776 // If our principals subsume the subject principal then use the subject
8777 // principal. Otherwise, use our principal to avoid running script in
8778 // elevated principals.
8780 nsCOMPtr
<nsIPrincipal
> subjectPrincipal
;
8782 rv
= nsContentUtils::GetSecurityManager()->
8783 GetSubjectPrincipal(getter_AddRefs(subjectPrincipal
));
8784 if (NS_FAILED(rv
)) {
8787 return NS_ERROR_FAILURE
;
8790 PRBool subsumes
= PR_FALSE
;
8791 nsCOMPtr
<nsIPrincipal
> ourPrincipal
= GetPrincipal();
8793 // Note the direction of this test: We don't allow setTimeouts running with
8794 // chrome privileges on content windows, but we do allow setTimeouts running
8795 // with content privileges on chrome windows (where they can't do very much,
8797 rv
= ourPrincipal
->Subsumes(subjectPrincipal
, &subsumes
);
8798 if (NS_FAILED(rv
)) {
8801 return NS_ERROR_FAILURE
;
8805 timeout
->mPrincipal
= subjectPrincipal
;
8807 timeout
->mPrincipal
= ourPrincipal
;
8810 TimeDuration delta
= TimeDuration::FromMilliseconds(realInterval
);
8812 if (!IsFrozen() && !mTimeoutsSuspendDepth
) {
8813 // If we're not currently frozen, then we set timeout->mWhen to be the
8814 // actual firing time of the timer (i.e., now + delta). We also actually
8815 // create a timer and fire it off.
8817 timeout
->mWhen
= TimeStamp::Now() + delta
;
8819 timeout
->mTimer
= do_CreateInstance("@mozilla.org/timer;1", &rv
);
8820 if (NS_FAILED(rv
)) {
8826 rv
= timeout
->mTimer
->InitWithFuncCallback(TimerCallback
, timeout
,
8828 nsITimer::TYPE_ONE_SHOT
);
8829 if (NS_FAILED(rv
)) {
8835 // The timeout is now also held in the timer's closure.
8838 // If we are frozen, however, then we instead simply set
8839 // timeout->mTimeRemaining to be the "time remaining" in the timeout (i.e.,
8840 // the interval itself). We don't create a timer for it, since that will
8841 // happen when we are thawed and the timeout will then get a timer and run
8844 timeout
->mTimeRemaining
= delta
;
8847 timeout
->mWindow
= this;
8850 timeout
->mNestingLevel
= nestingLevel
;
8853 // No popups from timeouts by default
8854 timeout
->mPopupState
= openAbused
;
8856 if (gRunningTimeoutDepth
== 0 && gPopupControlState
< openAbused
) {
8857 // This timeout is *not* set from another timeout and it's set
8858 // while popups are enabled. Propagate the state to the timeout if
8859 // its delay (interval) is equal to or less than what
8860 // "dom.disable_open_click_delay" is set to (in ms).
8863 nsContentUtils::GetIntPref("dom.disable_open_click_delay");
8865 if (interval
<= delay
) {
8866 timeout
->mPopupState
= gPopupControlState
;
8870 InsertTimeoutIntoList(timeout
);
8872 timeout
->mPublicId
= ++mTimeoutPublicIdCounter
;
8873 *aReturn
= timeout
->mPublicId
;
8875 // Our hold on the timeout is expiring. Note that this should not actually
8876 // free the timeout (since the list should have taken ownership as well).
8884 nsGlobalWindow::SetTimeoutOrInterval(PRBool aIsInterval
, PRInt32
*aReturn
)
8886 // This needs to forward to the inner window, but since the current
8887 // inner may not be the inner in the calling scope, we need to treat
8888 // this specially here as we don't want timeouts registered in a
8889 // dying inner window to get registered and run on the current inner
8890 // window. To get this right, we need to forward this call to the
8891 // inner window that's calling window.setTimeout().
8893 if (IsOuterWindow()) {
8894 nsGlobalWindow
* callerInner
= CallerInnerWindow();
8895 NS_ENSURE_TRUE(callerInner
, NS_ERROR_NOT_AVAILABLE
);
8897 // If the caller and the callee share the same outer window,
8898 // forward to the callee inner. Else, we forward to the current
8899 // inner (e.g. someone is calling setTimeout() on a reference to
8900 // some other window).
8902 if (callerInner
->GetOuterWindow() == this &&
8903 callerInner
->IsInnerWindow()) {
8904 return callerInner
->SetTimeoutOrInterval(aIsInterval
, aReturn
);
8907 FORWARD_TO_INNER(SetTimeoutOrInterval
, (aIsInterval
, aReturn
),
8908 NS_ERROR_NOT_INITIALIZED
);
8911 PRInt32 interval
= 0;
8912 PRBool isInterval
= aIsInterval
;
8913 nsCOMPtr
<nsIScriptTimeoutHandler
> handler
;
8914 nsresult rv
= NS_CreateJSTimeoutHandler(this,
8917 getter_AddRefs(handler
));
8919 return (rv
== NS_ERROR_DOM_TYPE_ERR
) ? NS_OK
: rv
;
8921 return SetTimeoutOrInterval(handler
, interval
, isInterval
, aReturn
);
8926 nsGlobalWindow::RunTimeout(nsTimeout
*aTimeout
)
8928 // If a modal dialog is open for this window, return early. Pending
8929 // timeouts will run when the modal dialog is dismissed.
8930 if (IsInModalState() || mTimeoutsSuspendDepth
) {
8936 NS_ASSERTION(IsInnerWindow(), "Timeout running on outer window!");
8937 NS_ASSERTION(!IsFrozen(), "Timeout running on a window in the bfcache!");
8939 nsTimeout
*nextTimeout
, *timeout
;
8940 nsTimeout
*last_expired_timeout
, *last_insertion_point
;
8941 nsTimeout dummy_timeout
;
8942 PRUint32 firingDepth
= mTimeoutFiringDepth
+ 1;
8944 // Make sure that the window and the script context don't go away as
8945 // a result of running timeouts
8946 nsCOMPtr
<nsIScriptGlobalObject
> windowKungFuDeathGrip(this);
8948 // A native timer has gone off. See which of our timeouts need
8950 TimeStamp now
= TimeStamp::Now();
8953 if (aTimeout
&& aTimeout
->mWhen
> now
) {
8954 // The OS timer fired early (yikes!), and possibly out of order
8955 // too. Set |deadline| to be the time when the OS timer *should*
8956 // have fired so that any timers that *should* have fired before
8957 // aTimeout *will* be fired now. This happens most of the time on
8960 deadline
= aTimeout
->mWhen
;
8965 // The timeout list is kept in deadline order. Discover the latest
8966 // timeout whose deadline has expired. On some platforms, native
8967 // timeout events fire "early", so we need to test the timer as well
8969 last_expired_timeout
= nsnull
;
8970 for (timeout
= FirstTimeout(); IsTimeout(timeout
); timeout
= timeout
->Next()) {
8971 if (((timeout
== aTimeout
) || (timeout
->mWhen
<= deadline
)) &&
8972 (timeout
->mFiringDepth
== 0)) {
8973 // Mark any timeouts that are on the list to be fired with the
8974 // firing depth so that we can reentrantly run timeouts
8975 timeout
->mFiringDepth
= firingDepth
;
8976 last_expired_timeout
= timeout
;
8980 // Maybe the timeout that the event was fired for has been deleted
8981 // and there are no others timeouts with deadlines that make them
8982 // eligible for execution yet. Go away.
8983 if (!last_expired_timeout
) {
8987 // Insert a dummy timeout into the list of timeouts between the
8988 // portion of the list that we are about to process now and those
8989 // timeouts that will be processed in a future call to
8990 // win_run_timeout(). This dummy timeout serves as the head of the
8991 // list for any timeouts inserted as a result of running a timeout.
8992 dummy_timeout
.mFiringDepth
= firingDepth
;
8993 dummy_timeout
.mWhen
= now
;
8994 PR_INSERT_AFTER(&dummy_timeout
, last_expired_timeout
);
8996 // Don't let ClearWindowTimeouts throw away our stack-allocated
8998 dummy_timeout
.AddRef();
8999 dummy_timeout
.AddRef();
9001 last_insertion_point
= mTimeoutInsertionPoint
;
9002 mTimeoutInsertionPoint
= &dummy_timeout
;
9004 for (timeout
= FirstTimeout();
9005 timeout
!= &dummy_timeout
&& !IsFrozen();
9006 timeout
= nextTimeout
) {
9007 nextTimeout
= timeout
->Next();
9009 if (timeout
->mFiringDepth
!= firingDepth
) {
9010 // We skip the timeout since it's on the list to run at another
9016 if (mTimeoutsSuspendDepth
) {
9017 // Some timer did suspend us. Make sure the
9018 // rest of the timers get executed later.
9019 timeout
->mFiringDepth
= 0;
9023 // The timeout is on the list to run at this depth, go ahead and
9026 // Get the script context (a strong ref to prevent it going away)
9027 // for this timeout and ensure the script language is enabled.
9028 nsCOMPtr
<nsIScriptContext
> scx
= GetScriptContextInternal(
9029 timeout
->mScriptHandler
->GetScriptTypeID());
9032 // No context means this window was closed or never properly
9033 // initialized for this language.
9037 // The "scripts disabled" concept is still a little vague wrt
9038 // multiple languages. Prepare for the day when languages can be
9039 // disabled independently of the other languages...
9040 if (!scx
->GetScriptsEnabled()) {
9041 // Scripts were enabled once in this window (unless aTimeout ==
9042 // nsnull) but now scripts are disabled (we might be in
9043 // print-preview, for instance), this means we shouldn't run any
9044 // timeouts at this point.
9046 // If scripts are enabled for this language in this window again
9047 // we'll fire the timeouts that are due at that point.
9051 // This timeout is good to run
9052 nsTimeout
*last_running_timeout
= mRunningTimeout
;
9053 mRunningTimeout
= timeout
;
9054 timeout
->mRunning
= PR_TRUE
;
9056 // Push this timeout's popup control state, which should only be
9057 // eabled the first time a timeout fires that was created while
9058 // popups were enabled and with a delay less than
9059 // "dom.disable_open_click_delay".
9060 nsAutoPopupStatePusher
popupStatePusher(timeout
->mPopupState
);
9062 // Clear the timeout's popup state, if any, to prevent interval
9063 // timeouts from repeatedly opening poups.
9064 timeout
->mPopupState
= openAbused
;
9066 // Hold on to the timeout in case mExpr or mFunObj releases its
9070 ++gRunningTimeoutDepth
;
9071 ++mTimeoutFiringDepth
;
9073 PRBool trackNestingLevel
= !timeout
->mInterval
;
9074 PRUint32 nestingLevel
;
9075 if (trackNestingLevel
) {
9076 nestingLevel
= sNestingLevel
;
9077 sNestingLevel
= timeout
->mNestingLevel
;
9080 nsCOMPtr
<nsIScriptTimeoutHandler
> handler(timeout
->mScriptHandler
);
9081 void *scriptObject
= handler
->GetScriptObject();
9082 if (!scriptObject
) {
9083 // Evaluate the timeout expression.
9084 const PRUnichar
*script
= handler
->GetHandlerText();
9085 NS_ASSERTION(script
, "timeout has no script nor handler text!");
9087 const char *filename
= nsnull
;
9088 PRUint32 lineNo
= 0;
9089 handler
->GetLocation(&filename
, &lineNo
);
9091 NS_TIME_FUNCTION_MARK("(file: %s, line: %d)", filename
, lineNo
);
9093 PRBool is_undefined
;
9094 scx
->EvaluateString(nsDependentString(script
),
9095 GetScriptGlobal(handler
->GetScriptTypeID()),
9096 timeout
->mPrincipal
, filename
, lineNo
,
9097 handler
->GetScriptVersion(), nsnull
,
9100 // Let the script handler know about the "secret" final argument that
9101 // indicates timeout lateness in milliseconds
9102 TimeDuration lateness
= now
- timeout
->mWhen
;
9104 handler
->SetLateness(lateness
.ToMilliseconds());
9106 nsCOMPtr
<nsIVariant
> dummy
;
9107 nsCOMPtr
<nsISupports
> me(static_cast<nsIDOMWindow
*>(this));
9108 scx
->CallEventHandler(me
,
9109 GetScriptGlobal(handler
->GetScriptTypeID()),
9110 scriptObject
, handler
->GetArgv(),
9111 // XXXmarkh - consider allowing CallEventHandler to
9113 getter_AddRefs(dummy
));
9116 handler
= nsnull
; // drop reference before dropping timeout refs.
9118 if (trackNestingLevel
) {
9119 sNestingLevel
= nestingLevel
;
9122 --mTimeoutFiringDepth
;
9123 --gRunningTimeoutDepth
;
9125 mRunningTimeout
= last_running_timeout
;
9126 timeout
->mRunning
= PR_FALSE
;
9128 // We ignore any failures from calling EvaluateString() or
9129 // CallEventHandler() on the context here since we're in a loop
9130 // where we're likely to be running timeouts whose OS timers
9131 // didn't fire in time and we don't want to not fire those timers
9132 // now just because execution of one timer failed. We can't
9133 // propagate the error to anyone who cares about it from this
9134 // point anyway, and the script context should have already reported
9135 // the script error in the usual way - so we just drop it.
9137 // If all timeouts were cleared and |timeout != aTimeout| then
9138 // |timeout| may be the last reference to the timeout so check if
9139 // it was cleared before releasing it.
9140 PRBool timeout_was_cleared
= timeout
->mCleared
;
9144 if (timeout_was_cleared
) {
9145 // The running timeout's window was cleared, this means that
9146 // ClearAllTimeouts() was called from a *nested* call, possibly
9147 // through a timeout that fired while a modal (to this window)
9148 // dialog was open or through other non-obvious paths.
9150 mTimeoutInsertionPoint
= last_insertion_point
;
9155 PRBool isInterval
= PR_FALSE
;
9157 // If we have a regular interval timer, we re-schedule the
9158 // timeout, accounting for clock drift.
9159 if (timeout
->mInterval
) {
9160 // Compute time to next timeout for interval timer.
9161 // Make sure nextInterval is at least DOMMinTimeoutValue().
9162 TimeDuration nextInterval
=
9163 TimeDuration::FromMilliseconds(NS_MAX(timeout
->mInterval
,
9164 PRUint32(DOMMinTimeoutValue())));
9166 // If we're running pending timeouts because they've been temporarily
9167 // disabled (!aTimeout), set the next interval to be relative to "now",
9168 // and not to when the timeout that was pending should have fired. Also
9169 // check if the next interval timeout is overdue. If so, then restart
9170 // the interval from now.
9171 TimeStamp firingTime
;
9172 if (!aTimeout
|| timeout
->mWhen
+ nextInterval
<= now
)
9173 firingTime
= now
+ nextInterval
;
9175 firingTime
= timeout
->mWhen
+ nextInterval
;
9177 TimeDuration delay
= firingTime
- TimeStamp::Now();
9179 // And make sure delay is nonnegative; that might happen if the timer
9180 // thread is firing our timers somewhat early.
9181 if (delay
< TimeDuration(0)) {
9182 delay
= TimeDuration(0);
9185 if (timeout
->mTimer
) {
9186 timeout
->mWhen
= firingTime
;
9188 // Reschedule the OS timer. Don't bother returning any error
9189 // codes if this fails since the callers of this method
9190 // doesn't care about them nobody who cares about them
9193 // Make sure to cast the unsigned PR_USEC_PER_MSEC to signed
9194 // PRTime to make the division do the right thing on 64-bit
9195 // platforms whether delay is positive or negative (which we
9196 // know is always positive here, but cast anyways for
9198 nsresult rv
= timeout
->mTimer
->
9199 InitWithFuncCallback(TimerCallback
, timeout
,
9200 delay
.ToMilliseconds(),
9201 nsITimer::TYPE_ONE_SHOT
);
9203 if (NS_FAILED(rv
)) {
9204 NS_ERROR("Error initializing timer for DOM timeout!");
9206 // We failed to initialize the new OS timer, this timer does
9207 // us no good here so we just cancel it (just in case) and
9208 // null out the pointer to the OS timer, this will release the
9209 // OS timer. As we continue executing the code below we'll end
9210 // up deleting the timeout since it's not an interval timeout
9211 // any more (since timeout->mTimer == nsnull).
9212 timeout
->mTimer
->Cancel();
9213 timeout
->mTimer
= nsnull
;
9215 // Now that the OS timer no longer has a reference to the
9216 // timeout we need to drop that reference.
9220 NS_ASSERTION(IsFrozen() || mTimeoutsSuspendDepth
,
9221 "How'd our timer end up null if we're not frozen or "
9224 timeout
->mTimeRemaining
= delay
;
9225 isInterval
= PR_TRUE
;
9229 if (timeout
->mTimer
) {
9230 if (timeout
->mInterval
) {
9231 isInterval
= PR_TRUE
;
9233 // The timeout still has an OS timer, and it's not an
9234 // interval, that means that the OS timer could still fire (if
9235 // it didn't already, i.e. aTimeout == timeout), cancel the OS
9236 // timer and release its reference to the timeout.
9237 timeout
->mTimer
->Cancel();
9238 timeout
->mTimer
= nsnull
;
9244 // Running a timeout can cause another timeout to be deleted, so
9245 // we need to reset the pointer to the following timeout.
9246 nextTimeout
= timeout
->Next();
9248 PR_REMOVE_LINK(timeout
);
9251 // Reschedule an interval timeout. Insert interval timeout
9252 // onto list sorted in deadline order.
9254 InsertTimeoutIntoList(timeout
);
9257 // Release the timeout struct since it's possibly out of the list
9261 // Take the dummy timeout off the head of the list
9262 PR_REMOVE_LINK(&dummy_timeout
);
9264 mTimeoutInsertionPoint
= last_insertion_point
;
9268 nsTimeout::Release()
9273 // language specific cleanup done as mScriptHandler destructs...
9275 // Kill the timer if it is still alive.
9293 nsGlobalWindow::ClearTimeoutOrInterval(PRInt32 aTimerID
)
9295 FORWARD_TO_INNER(ClearTimeoutOrInterval
, (aTimerID
), NS_ERROR_NOT_INITIALIZED
);
9297 PRUint32 public_id
= (PRUint32
)aTimerID
;
9300 for (timeout
= FirstTimeout();
9302 timeout
= timeout
->Next()) {
9303 if (timeout
->mPublicId
== public_id
) {
9304 if (timeout
->mRunning
) {
9305 /* We're running from inside the timeout. Mark this
9306 timeout for deferred deletion by the code in
9308 timeout
->mInterval
= 0;
9311 /* Delete the timeout from the pending timeout list */
9312 PR_REMOVE_LINK(timeout
);
9314 if (timeout
->mTimer
) {
9315 timeout
->mTimer
->Cancel();
9316 timeout
->mTimer
= nsnull
;
9328 // A JavaScript specific version.
9330 nsGlobalWindow::ClearTimeoutOrInterval()
9332 FORWARD_TO_INNER(ClearTimeoutOrInterval
, (), NS_ERROR_NOT_INITIALIZED
);
9334 nsresult rv
= NS_OK
;
9335 nsAXPCNativeCallContext
*ncc
= nsnull
;
9337 rv
= nsContentUtils::XPConnect()->
9338 GetCurrentNativeCallContext(&ncc
);
9339 NS_ENSURE_SUCCESS(rv
, rv
);
9342 return NS_ERROR_NOT_AVAILABLE
;
9344 JSContext
*cx
= nsnull
;
9346 rv
= ncc
->GetJSContext(&cx
);
9347 NS_ENSURE_SUCCESS(rv
, rv
);
9351 ncc
->GetArgc(&argc
);
9354 // No arguments, return early.
9359 jsval
*argv
= nsnull
;
9361 ncc
->GetArgvPtr(&argv
);
9365 JSAutoRequest
ar(cx
);
9367 // XXXjst: Can we deal with this w/o using GetCurrentNativeCallContext()
9368 if (argv
[0] == JSVAL_VOID
|| !::JS_ValueToInt32(cx
, argv
[0], &timer_id
) ||
9370 // Undefined or non-positive number passed as argument, return
9371 // early. Make sure that JS_ValueToInt32 didn't set an exception.
9373 ::JS_ClearPendingException(cx
);
9377 return ClearTimeoutOrInterval(timer_id
);
9381 nsGlobalWindow::ClearAllTimeouts()
9383 nsTimeout
*timeout
, *nextTimeout
;
9385 for (timeout
= FirstTimeout(); IsTimeout(timeout
); timeout
= nextTimeout
) {
9386 /* If RunTimeout() is higher up on the stack for this
9387 window, e.g. as a result of document.write from a timeout,
9388 then we need to reset the list insertion point for
9389 newly-created timeouts in case the user adds a timeout,
9390 before we pop the stack back to RunTimeout. */
9391 if (mRunningTimeout
== timeout
)
9392 mTimeoutInsertionPoint
= nsnull
;
9394 nextTimeout
= timeout
->Next();
9396 if (timeout
->mTimer
) {
9397 timeout
->mTimer
->Cancel();
9398 timeout
->mTimer
= nsnull
;
9400 // Drop the count since the timer isn't going to hold on
9405 // Set timeout->mCleared to true to indicate that the timeout was
9406 // cleared and taken out of the list of timeouts
9407 timeout
->mCleared
= PR_TRUE
;
9409 // Drop the count since we're removing it from the list.
9413 // Clear out our list
9414 PR_INIT_CLIST(&mTimeouts
);
9418 nsGlobalWindow::InsertTimeoutIntoList(nsTimeout
*aTimeout
)
9420 NS_ASSERTION(IsInnerWindow(),
9421 "InsertTimeoutIntoList() called on outer window!");
9423 // Start at mLastTimeout and go backwards. Don't go further than
9424 // mTimeoutInsertionPoint, though. This optimizes for the common case of
9425 // insertion at the end.
9426 nsTimeout
* prevSibling
;
9427 for (prevSibling
= LastTimeout();
9428 IsTimeout(prevSibling
) && prevSibling
!= mTimeoutInsertionPoint
&&
9429 // This condition needs to match the one in SetTimeoutOrInterval that
9430 // determines whether to set mWhen or mTimeRemaining.
9431 ((IsFrozen() || mTimeoutsSuspendDepth
) ?
9432 prevSibling
->mTimeRemaining
> aTimeout
->mTimeRemaining
:
9433 prevSibling
->mWhen
> aTimeout
->mWhen
);
9434 prevSibling
= prevSibling
->Prev()) {
9435 /* Do nothing; just searching */
9438 // Now link in aTimeout after prevSibling.
9439 PR_INSERT_AFTER(aTimeout
, prevSibling
);
9441 aTimeout
->mFiringDepth
= 0;
9443 // Increment the timeout's reference count since it's now held on to
9450 nsGlobalWindow::TimerCallback(nsITimer
*aTimer
, void *aClosure
)
9452 nsTimeout
*timeout
= (nsTimeout
*)aClosure
;
9454 // Hold on to the timeout to ensure it doesn't go away while it's
9455 // being handled (aka kungFuDeathGrip).
9458 timeout
->mWindow
->RunTimeout(timeout
);
9460 // Drop our reference to the timeout now that we're done with it.
9464 //*****************************************************************************
9465 // nsGlobalWindow: Helper Functions
9466 //*****************************************************************************
9469 nsGlobalWindow::GetTreeOwner(nsIDocShellTreeOwner
**aTreeOwner
)
9471 FORWARD_TO_OUTER(GetTreeOwner
, (aTreeOwner
), NS_ERROR_NOT_INITIALIZED
);
9473 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
9475 // If there's no docShellAsItem, this window must have been closed,
9476 // in that case there is no tree owner.
9478 if (!docShellAsItem
) {
9479 *aTreeOwner
= nsnull
;
9484 return docShellAsItem
->GetTreeOwner(aTreeOwner
);
9488 nsGlobalWindow::GetTreeOwner(nsIBaseWindow
**aTreeOwner
)
9490 FORWARD_TO_OUTER(GetTreeOwner
, (aTreeOwner
), NS_ERROR_NOT_INITIALIZED
);
9492 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
9493 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
9495 // If there's no docShellAsItem, this window must have been closed,
9496 // in that case there is no tree owner.
9498 if (docShellAsItem
) {
9499 docShellAsItem
->GetTreeOwner(getter_AddRefs(treeOwner
));
9503 *aTreeOwner
= nsnull
;
9507 return CallQueryInterface(treeOwner
, aTreeOwner
);
9511 nsGlobalWindow::GetWebBrowserChrome(nsIWebBrowserChrome
**aBrowserChrome
)
9513 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
9514 GetTreeOwner(getter_AddRefs(treeOwner
));
9516 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome(do_GetInterface(treeOwner
));
9517 NS_IF_ADDREF(*aBrowserChrome
= browserChrome
);
9522 nsIScrollableFrame
*
9523 nsGlobalWindow::GetScrollFrame()
9525 FORWARD_TO_OUTER(GetScrollFrame
, (), nsnull
);
9531 nsCOMPtr
<nsIPresShell
> presShell
;
9532 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
9534 return presShell
->GetRootScrollFrameAsScrollable();
9540 nsGlobalWindow::BuildURIfromBase(const char *aURL
, nsIURI
**aBuiltURI
,
9541 PRBool
*aFreeSecurityPass
,
9542 JSContext
**aCXused
)
9544 nsIScriptContext
*scx
= GetContextInternal();
9545 JSContext
*cx
= nsnull
;
9547 *aBuiltURI
= nsnull
;
9548 *aFreeSecurityPass
= PR_FALSE
;
9553 NS_ASSERTION(scx
, "opening window missing its context");
9554 NS_ASSERTION(mDocument
, "opening window missing its document");
9555 if (!scx
|| !mDocument
)
9556 return NS_ERROR_FAILURE
;
9558 nsCOMPtr
<nsIDOMChromeWindow
> chrome_win
=
9559 do_QueryInterface(static_cast<nsIDOMWindow
*>(this));
9561 if (nsContentUtils::IsCallerChrome() && !chrome_win
) {
9562 // If open() is called from chrome on a non-chrome window, we'll
9563 // use the context from the window on which open() is being called
9564 // to prevent giving chrome priveleges to new windows opened in
9565 // such a way. This also makes us get the appropriate base URI for
9566 // the below URI resolution code.
9568 cx
= (JSContext
*)scx
->GetNativeContext();
9570 // get the JSContext from the call stack
9571 nsCOMPtr
<nsIThreadJSContextStack
> stack(do_GetService(sJSStackContractID
));
9576 /* resolve the URI, which could be relative to the calling window
9577 (note the algorithm to get the base URI should match the one
9578 used to actually kick off the load in nsWindowWatcher.cpp). */
9579 nsCAutoString
charset(NS_LITERAL_CSTRING("UTF-8")); // default to utf-8
9580 nsIURI
* baseURI
= nsnull
;
9581 nsCOMPtr
<nsIURI
> uriToLoad
;
9582 nsCOMPtr
<nsIDOMWindow
> sourceWindow
;
9585 nsIScriptContext
*scriptcx
= nsJSUtils::GetDynamicScriptContext(cx
);
9587 sourceWindow
= do_QueryInterface(scriptcx
->GetGlobalObject());
9590 if (!sourceWindow
) {
9591 sourceWindow
= do_QueryInterface(NS_ISUPPORTS_CAST(nsIDOMWindow
*, this));
9592 *aFreeSecurityPass
= PR_TRUE
;
9596 nsCOMPtr
<nsIDOMDocument
> domDoc
;
9597 sourceWindow
->GetDocument(getter_AddRefs(domDoc
));
9598 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(domDoc
));
9600 baseURI
= doc
->GetDocBaseURI();
9601 charset
= doc
->GetDocumentCharacterSet();
9607 return NS_NewURI(aBuiltURI
, nsDependentCString(aURL
), charset
.get(), baseURI
);
9611 nsGlobalWindow::SecurityCheckURL(const char *aURL
)
9615 nsCOMPtr
<nsIURI
> uri
;
9617 if (NS_FAILED(BuildURIfromBase(aURL
, getter_AddRefs(uri
), &freePass
, &cx
)))
9618 return NS_ERROR_FAILURE
;
9620 if (!freePass
&& NS_FAILED(nsContentUtils::GetSecurityManager()->
9621 CheckLoadURIFromScript(cx
, uri
)))
9622 return NS_ERROR_FAILURE
;
9628 nsGlobalWindow::FlushPendingNotifications(mozFlushType aType
)
9631 mDoc
->FlushPendingNotifications(aType
);
9636 nsGlobalWindow::EnsureSizeUpToDate()
9638 // If we're a subframe, make sure our size is up to date. It's OK that this
9639 // crosses the content/chrome boundary, since chrome can have pending reflows
9641 nsGlobalWindow
*parent
=
9642 static_cast<nsGlobalWindow
*>(GetPrivateParent());
9644 parent
->FlushPendingNotifications(Flush_Layout
);
9649 nsGlobalWindow::SaveWindowState(nsISupports
**aState
)
9651 NS_PRECONDITION(IsOuterWindow(), "Can't save the inner window's state");
9655 if (!mContext
|| !mJSObject
) {
9656 // The window may be getting torn down; don't bother saving state.
9660 nsGlobalWindow
*inner
= GetCurrentInnerWindowInternal();
9661 NS_ASSERTION(inner
, "No inner window to save");
9663 // Don't do anything else to this inner window! After this point, all
9664 // calls to SetTimeoutOrInterval will create entries in the timeout
9665 // list that will only run after this window has come out of the bfcache.
9666 // Also, while we're frozen, we won't dispatch online/offline events
9670 // Remember the outer window's prototype.
9671 JSContext
*cx
= (JSContext
*)mContext
->GetNativeContext();
9672 JSAutoRequest
req(cx
);
9674 nsIXPConnect
*xpc
= nsContentUtils::XPConnect();
9676 nsCOMPtr
<nsIClassInfo
> ci
=
9677 do_QueryInterface((nsIScriptGlobalObject
*)this);
9678 nsCOMPtr
<nsIXPConnectJSObjectHolder
> proto
;
9679 nsresult rv
= xpc
->GetWrappedNativePrototype(cx
, mJSObject
, ci
,
9680 getter_AddRefs(proto
));
9681 NS_ENSURE_SUCCESS(rv
, rv
);
9683 JSObject
*realProto
= JS_GetPrototype(cx
, mJSObject
);
9684 nsCOMPtr
<nsIXPConnectJSObjectHolder
> realProtoHolder
;
9686 rv
= xpc
->HoldObject(cx
, realProto
, getter_AddRefs(realProtoHolder
));
9687 NS_ENSURE_SUCCESS(rv
, rv
);
9690 nsCOMPtr
<nsISupports
> state
= new WindowStateHolder(inner
,
9695 NS_ENSURE_TRUE(state
, NS_ERROR_OUT_OF_MEMORY
);
9698 proto
->GetJSObject(&wnProto
);
9699 if (!JS_SetPrototype(cx
, mJSObject
, wnProto
)) {
9700 return NS_ERROR_FAILURE
;
9703 #ifdef DEBUG_PAGE_CACHE
9704 printf("saving window state, state = %p\n", (void*)state
);
9707 state
.swap(*aState
);
9712 nsGlobalWindow::RestoreWindowState(nsISupports
*aState
)
9714 NS_ASSERTION(IsOuterWindow(), "Cannot restore an inner window");
9716 if (!mContext
|| !mJSObject
) {
9717 // The window may be getting torn down; don't bother restoring state.
9721 nsCOMPtr
<WindowStateHolder
> holder
= do_QueryInterface(aState
);
9722 NS_ENSURE_TRUE(holder
, NS_ERROR_FAILURE
);
9724 #ifdef DEBUG_PAGE_CACHE
9725 printf("restoring window state, state = %p\n", (void*)holder
);
9728 // And we're ready to go!
9729 nsGlobalWindow
*inner
= GetCurrentInnerWindowInternal();
9731 // if a link is focused, refocus with the FLAG_SHOWRING flag set. This makes
9732 // it easy to tell which link was last clicked when going back a page.
9733 nsIContent
* focusedNode
= inner
->GetFocusedNode();
9734 if (IsLink(focusedNode
)) {
9735 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
9737 nsCOMPtr
<nsIDOMElement
> focusedElement(do_QueryInterface(focusedNode
));
9738 fm
->SetFocus(focusedElement
, nsIFocusManager::FLAG_NOSCROLL
|
9739 nsIFocusManager::FLAG_SHOWRING
);
9745 holder
->DidRestoreWindow();
9751 nsGlobalWindow::SuspendTimeouts(PRUint32 aIncrease
,
9752 PRBool aFreezeChildren
)
9754 FORWARD_TO_INNER_VOID(SuspendTimeouts
, (aIncrease
, aFreezeChildren
));
9756 PRBool suspended
= (mTimeoutsSuspendDepth
!= 0);
9757 mTimeoutsSuspendDepth
+= aIncrease
;
9760 DisableAccelerationUpdates();
9762 nsDOMThreadService
* dts
= nsDOMThreadService::get();
9764 dts
->SuspendWorkersForGlobal(static_cast<nsIScriptGlobalObject
*>(this));
9767 TimeStamp now
= TimeStamp::Now();
9768 for (nsTimeout
*t
= FirstTimeout(); IsTimeout(t
); t
= t
->Next()) {
9769 // Set mTimeRemaining to be the time remaining for this timer.
9771 t
->mTimeRemaining
= t
->mWhen
- now
;
9773 t
->mTimeRemaining
= TimeDuration(0);
9775 // Drop the XPCOM timer; we'll reschedule when restoring the state.
9777 t
->mTimer
->Cancel();
9780 // Drop the reference that the timer's closure had on this timeout, we'll
9781 // add it back in ResumeTimeouts. Note that it shouldn't matter that we're
9782 // passing null for the context, since this shouldn't actually release this
9789 // Suspend our children as well.
9790 nsCOMPtr
<nsIDocShellTreeNode
> node(do_QueryInterface(GetDocShell()));
9792 PRInt32 childCount
= 0;
9793 node
->GetChildCount(&childCount
);
9795 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
9796 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
9797 node
->GetChildAt(i
, getter_AddRefs(childShell
));
9798 NS_ASSERTION(childShell
, "null child shell");
9800 nsCOMPtr
<nsPIDOMWindow
> pWin
= do_GetInterface(childShell
);
9802 nsGlobalWindow
*win
=
9803 static_cast<nsGlobalWindow
*>
9804 (static_cast<nsPIDOMWindow
*>(pWin
));
9805 NS_ASSERTION(win
->IsOuterWindow(), "Expected outer window");
9806 nsGlobalWindow
* inner
= win
->GetCurrentInnerWindowInternal();
9808 // This is a bit hackish. Only freeze/suspend windows which are truly our
9810 nsCOMPtr
<nsIContent
> frame
= do_QueryInterface(pWin
->GetFrameElementInternal());
9811 if (!mDoc
|| !frame
|| mDoc
!= frame
->GetOwnerDoc() || !inner
) {
9815 win
->SuspendTimeouts(aIncrease
, aFreezeChildren
);
9817 if (inner
&& aFreezeChildren
) {
9826 nsGlobalWindow::ResumeTimeouts(PRBool aThawChildren
)
9828 FORWARD_TO_INNER(ResumeTimeouts
, (), NS_ERROR_NOT_INITIALIZED
);
9830 NS_ASSERTION(mTimeoutsSuspendDepth
, "Mismatched calls to ResumeTimeouts!");
9831 --mTimeoutsSuspendDepth
;
9832 PRBool shouldResume
= (mTimeoutsSuspendDepth
== 0);
9836 EnableAccelerationUpdates();
9838 nsDOMThreadService
* dts
= nsDOMThreadService::get();
9840 dts
->ResumeWorkersForGlobal(static_cast<nsIScriptGlobalObject
*>(this));
9843 // Restore all of the timeouts, using the stored time remaining
9844 // (stored in timeout->mTimeRemaining).
9846 TimeStamp now
= TimeStamp::Now();
9849 PRBool _seenDummyTimeout
= PR_FALSE
;
9852 for (nsTimeout
*t
= FirstTimeout(); IsTimeout(t
); t
= t
->Next()) {
9853 // There's a chance we're being called with RunTimeout on the stack in which
9854 // case we have a dummy timeout in the list that *must not* be resumed. It
9855 // can be identified by a null mWindow.
9858 NS_ASSERTION(!_seenDummyTimeout
, "More than one dummy timeout?!");
9859 _seenDummyTimeout
= PR_TRUE
;
9864 // XXXbz the combination of the way |delay| and |t->mWhen| are set here
9865 // makes no sense. Are we trying to impose that min timeout value or
9868 NS_MAX(PRInt32(t
->mTimeRemaining
.ToMilliseconds()),
9869 DOMMinTimeoutValue());
9871 // Set mWhen back to the time when the timer is supposed to
9873 t
->mWhen
= now
+ t
->mTimeRemaining
;
9875 t
->mTimer
= do_CreateInstance("@mozilla.org/timer;1");
9876 NS_ENSURE_TRUE(t
->mTimer
, NS_ERROR_OUT_OF_MEMORY
);
9878 rv
= t
->mTimer
->InitWithFuncCallback(TimerCallback
, t
, delay
,
9879 nsITimer::TYPE_ONE_SHOT
);
9880 if (NS_FAILED(rv
)) {
9885 // Add a reference for the new timer's closure.
9890 // Resume our children as well.
9891 nsCOMPtr
<nsIDocShellTreeNode
> node
=
9892 do_QueryInterface(GetDocShell());
9894 PRInt32 childCount
= 0;
9895 node
->GetChildCount(&childCount
);
9897 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
9898 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
9899 node
->GetChildAt(i
, getter_AddRefs(childShell
));
9900 NS_ASSERTION(childShell
, "null child shell");
9902 nsCOMPtr
<nsPIDOMWindow
> pWin
= do_GetInterface(childShell
);
9904 nsGlobalWindow
*win
=
9905 static_cast<nsGlobalWindow
*>
9906 (static_cast<nsPIDOMWindow
*>(pWin
));
9908 NS_ASSERTION(win
->IsOuterWindow(), "Expected outer window");
9909 nsGlobalWindow
* inner
= win
->GetCurrentInnerWindowInternal();
9911 // This is a bit hackish. Only thaw/resume windows which are truly our
9913 nsCOMPtr
<nsIContent
> frame
= do_QueryInterface(pWin
->GetFrameElementInternal());
9914 if (!mDoc
|| !frame
|| mDoc
!= frame
->GetOwnerDoc() || !inner
) {
9918 if (inner
&& aThawChildren
) {
9922 rv
= win
->ResumeTimeouts(aThawChildren
);
9923 NS_ENSURE_SUCCESS(rv
, rv
);
9932 nsGlobalWindow::TimeoutSuspendCount()
9934 FORWARD_TO_INNER(TimeoutSuspendCount
, (), 0);
9935 return mTimeoutsSuspendDepth
;
9939 nsGlobalWindow::GetScriptTypeID(PRUint32
*aScriptType
)
9941 NS_ERROR("No default script type here - ask some element");
9942 return nsIProgrammingLanguage::UNKNOWN
;
9946 nsGlobalWindow::SetScriptTypeID(PRUint32 aScriptType
)
9948 NS_ERROR("Can't change default script type for a document");
9949 return NS_ERROR_NOT_IMPLEMENTED
;
9953 nsGlobalWindow::SetHasOrientationEventListener()
9955 mHasAcceleration
= PR_TRUE
;
9956 EnableAccelerationUpdates();
9960 nsGlobalWindow::GetURL(nsIDOMMozURLProperty
** aURL
)
9962 FORWARD_TO_INNER(GetURL
, (aURL
), NS_ERROR_UNEXPECTED
);
9964 if (!mURLProperty
) {
9965 mURLProperty
= new nsDOMMozURLProperty(this);
9968 NS_ADDREF(*aURL
= mURLProperty
);
9973 // nsGlobalChromeWindow implementation
9975 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow
)
9976 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow
,
9978 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mBrowserDOMWindow
)
9979 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMessageManager
)
9980 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
9982 DOMCI_DATA(ChromeWindow
, nsGlobalChromeWindow
)
9984 // QueryInterface implementation for nsGlobalChromeWindow
9985 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsGlobalChromeWindow
)
9986 NS_INTERFACE_MAP_ENTRY(nsIDOMChromeWindow
)
9987 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ChromeWindow
)
9988 NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow
)
9990 NS_IMPL_ADDREF_INHERITED(nsGlobalChromeWindow
, nsGlobalWindow
)
9991 NS_IMPL_RELEASE_INHERITED(nsGlobalChromeWindow
, nsGlobalWindow
)
9994 nsGlobalChromeWindow::GetWindowState(PRUint16
* aWindowState
)
9996 *aWindowState
= nsIDOMChromeWindow::STATE_NORMAL
;
9998 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
10003 nsresult rv
= widget
->GetSizeMode(&aMode
);
10004 NS_ENSURE_SUCCESS(rv
, rv
);
10008 case nsSizeMode_Minimized
:
10009 *aWindowState
= nsIDOMChromeWindow::STATE_MINIMIZED
;
10011 case nsSizeMode_Maximized
:
10012 *aWindowState
= nsIDOMChromeWindow::STATE_MAXIMIZED
;
10014 case nsSizeMode_Fullscreen
:
10015 *aWindowState
= nsIDOMChromeWindow::STATE_FULLSCREEN
;
10017 case nsSizeMode_Normal
:
10018 *aWindowState
= nsIDOMChromeWindow::STATE_NORMAL
;
10021 NS_WARNING("Illegal window state for this chrome window");
10029 nsGlobalChromeWindow::Maximize()
10031 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
10032 nsresult rv
= NS_OK
;
10035 rv
= widget
->SetSizeMode(nsSizeMode_Maximized
);
10042 nsGlobalChromeWindow::Minimize()
10044 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
10045 nsresult rv
= NS_OK
;
10048 rv
= widget
->SetSizeMode(nsSizeMode_Minimized
);
10054 nsGlobalChromeWindow::Restore()
10056 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
10057 nsresult rv
= NS_OK
;
10060 rv
= widget
->SetSizeMode(nsSizeMode_Normal
);
10067 nsGlobalChromeWindow::GetAttention()
10069 return GetAttentionWithCycleCount(-1);
10073 nsGlobalChromeWindow::GetAttentionWithCycleCount(PRInt32 aCycleCount
)
10075 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
10076 nsresult rv
= NS_OK
;
10079 rv
= widget
->GetAttention(aCycleCount
);
10086 nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent
*aMouseDownEvent
)
10088 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
10093 nsCOMPtr
<nsIPrivateDOMEvent
> privEvent
= do_QueryInterface(aMouseDownEvent
);
10094 NS_ENSURE_TRUE(privEvent
, NS_ERROR_FAILURE
);
10095 nsEvent
*internalEvent
= privEvent
->GetInternalNSEvent();
10096 NS_ENSURE_TRUE(internalEvent
&&
10097 internalEvent
->eventStructType
== NS_MOUSE_EVENT
,
10099 nsMouseEvent
*mouseEvent
= static_cast<nsMouseEvent
*>(internalEvent
);
10101 return widget
->BeginMoveDrag(mouseEvent
);
10104 //Note: This call will lock the cursor, it will not change as it moves.
10105 //To unlock, the cursor must be set back to CURSOR_AUTO.
10107 nsGlobalChromeWindow::SetCursor(const nsAString
& aCursor
)
10109 FORWARD_TO_OUTER_CHROME(SetCursor
, (aCursor
), NS_ERROR_NOT_INITIALIZED
);
10111 nsresult rv
= NS_OK
;
10114 // use C strings to keep the code/data size down
10115 NS_ConvertUTF16toUTF8
cursorString(aCursor
);
10117 if (cursorString
.Equals("auto"))
10118 cursor
= NS_STYLE_CURSOR_AUTO
;
10120 nsCSSKeyword keyword
= nsCSSKeywords::LookupKeyword(aCursor
);
10121 if (eCSSKeyword_UNKNOWN
== keyword
||
10122 !nsCSSProps::FindKeyword(keyword
, nsCSSProps::kCursorKTable
, cursor
)) {
10123 // XXX remove the following three values (leave return NS_OK) after 1.8
10124 // XXX since they should have been -moz- prefixed (covered by FindKeyword).
10125 // XXX (also remove |cursorString| at that point?).
10126 if (cursorString
.Equals("grab"))
10127 cursor
= NS_STYLE_CURSOR_GRAB
;
10128 else if (cursorString
.Equals("grabbing"))
10129 cursor
= NS_STYLE_CURSOR_GRABBING
;
10130 else if (cursorString
.Equals("spinning"))
10131 cursor
= NS_STYLE_CURSOR_SPINNING
;
10137 nsRefPtr
<nsPresContext
> presContext
;
10139 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
10143 // Need root widget.
10144 nsCOMPtr
<nsIPresShell
> presShell
;
10145 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
10146 NS_ENSURE_TRUE(presShell
, NS_ERROR_FAILURE
);
10148 nsIViewManager
* vm
= presShell
->GetViewManager();
10149 NS_ENSURE_TRUE(vm
, NS_ERROR_FAILURE
);
10152 vm
->GetRootView(rootView
);
10153 NS_ENSURE_TRUE(rootView
, NS_ERROR_FAILURE
);
10155 nsIWidget
* widget
= rootView
->GetNearestWidget(nsnull
);
10156 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
10158 // Call esm and set cursor.
10159 rv
= presContext
->EventStateManager()->SetCursor(cursor
, nsnull
,
10160 PR_FALSE
, 0.0f
, 0.0f
,
10168 nsGlobalChromeWindow::GetBrowserDOMWindow(nsIBrowserDOMWindow
**aBrowserWindow
)
10170 FORWARD_TO_OUTER_CHROME(GetBrowserDOMWindow
, (aBrowserWindow
),
10171 NS_ERROR_NOT_INITIALIZED
);
10173 NS_ENSURE_ARG_POINTER(aBrowserWindow
);
10175 *aBrowserWindow
= mBrowserDOMWindow
;
10176 NS_IF_ADDREF(*aBrowserWindow
);
10181 nsGlobalChromeWindow::SetBrowserDOMWindow(nsIBrowserDOMWindow
*aBrowserWindow
)
10183 FORWARD_TO_OUTER_CHROME(SetBrowserDOMWindow
, (aBrowserWindow
),
10184 NS_ERROR_NOT_INITIALIZED
);
10186 mBrowserDOMWindow
= aBrowserWindow
;
10191 nsGlobalChromeWindow::NotifyDefaultButtonLoaded(nsIDOMElement
* aDefaultButton
)
10194 NS_ENSURE_ARG(aDefaultButton
);
10196 // Don't snap to a disabled button.
10197 nsCOMPtr
<nsIDOMXULControlElement
> xulControl
=
10198 do_QueryInterface(aDefaultButton
);
10199 NS_ENSURE_TRUE(xulControl
, NS_ERROR_FAILURE
);
10201 nsresult rv
= xulControl
->GetDisabled(&disabled
);
10202 NS_ENSURE_SUCCESS(rv
, rv
);
10206 // Get the button rect in screen coordinates.
10207 nsCOMPtr
<nsIContent
> content(do_QueryInterface(aDefaultButton
));
10208 NS_ENSURE_TRUE(content
, NS_ERROR_FAILURE
);
10209 nsIFrame
*frame
= content
->GetPrimaryFrame();
10210 NS_ENSURE_TRUE(frame
, NS_ERROR_FAILURE
);
10211 nsIntRect buttonRect
= frame
->GetScreenRect();
10213 // Get the widget rect in screen coordinates.
10214 nsIWidget
*widget
= GetNearestWidget();
10215 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
10216 nsIntRect widgetRect
;
10217 rv
= widget
->GetScreenBounds(widgetRect
);
10218 NS_ENSURE_SUCCESS(rv
, rv
);
10220 // Convert the buttonRect coordinates from screen to the widget.
10221 buttonRect
-= widgetRect
.TopLeft();
10222 rv
= widget
->OnDefaultButtonLoaded(buttonRect
);
10223 if (rv
== NS_ERROR_NOT_IMPLEMENTED
)
10227 return NS_ERROR_NOT_IMPLEMENTED
;
10232 nsGlobalChromeWindow::GetMessageManager(nsIChromeFrameMessageManager
** aManager
)
10234 FORWARD_TO_INNER_CHROME(GetMessageManager
, (aManager
), NS_ERROR_FAILURE
);
10235 if (!mMessageManager
) {
10236 nsIScriptContext
* scx
= GetContextInternal();
10237 NS_ENSURE_STATE(scx
);
10238 JSContext
* cx
= (JSContext
*)scx
->GetNativeContext();
10239 NS_ENSURE_STATE(cx
);
10240 nsCOMPtr
<nsIChromeFrameMessageManager
> globalMM
=
10241 do_GetService("@mozilla.org/globalmessagemanager;1");
10243 new nsFrameMessageManager(PR_TRUE
,
10248 static_cast<nsFrameMessageManager
*>(globalMM
.get()),
10250 NS_ENSURE_TRUE(mMessageManager
, NS_ERROR_OUT_OF_MEMORY
);
10252 CallQueryInterface(mMessageManager
, aManager
);
10256 // nsGlobalModalWindow implementation
10258 // QueryInterface implementation for nsGlobalModalWindow
10259 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalModalWindow
)
10260 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalModalWindow
,
10262 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mReturnValue
)
10263 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
10265 DOMCI_DATA(ModalContentWindow
, nsGlobalModalWindow
)
10267 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsGlobalModalWindow
)
10268 NS_INTERFACE_MAP_ENTRY(nsIDOMModalContentWindow
)
10269 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ModalContentWindow
)
10270 NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow
)
10272 NS_IMPL_ADDREF_INHERITED(nsGlobalModalWindow
, nsGlobalWindow
)
10273 NS_IMPL_RELEASE_INHERITED(nsGlobalModalWindow
, nsGlobalWindow
)
10276 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGlobalModalWindow
,
10278 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mReturnValue
)
10279 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
10283 nsGlobalModalWindow::GetDialogArguments(nsIArray
**aArguments
)
10285 FORWARD_TO_INNER_MODAL_CONTENT_WINDOW(GetDialogArguments
, (aArguments
),
10286 NS_ERROR_NOT_INITIALIZED
);
10288 PRBool subsumes
= PR_FALSE
;
10289 nsIPrincipal
*self
= GetPrincipal();
10290 if (self
&& NS_SUCCEEDED(self
->Subsumes(mArgumentsOrigin
, &subsumes
)) &&
10292 NS_IF_ADDREF(*aArguments
= mArguments
);
10294 *aArguments
= nsnull
;
10301 nsGlobalModalWindow::GetReturnValue(nsIVariant
**aRetVal
)
10303 FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(GetReturnValue
, (aRetVal
), NS_OK
);
10305 NS_IF_ADDREF(*aRetVal
= mReturnValue
);
10311 nsGlobalModalWindow::SetReturnValue(nsIVariant
*aRetVal
)
10313 FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(SetReturnValue
, (aRetVal
), NS_OK
);
10315 mReturnValue
= aRetVal
;
10321 nsGlobalModalWindow::SetNewDocument(nsIDocument
*aDocument
,
10322 nsISupports
*aState
,
10323 PRBool aForceReuseInnerWindow
)
10325 // If we're loading a new document into a modal dialog, clear the
10326 // return value that was set, if any, by the current document.
10328 mReturnValue
= nsnull
;
10331 return nsGlobalWindow::SetNewDocument(aDocument
, aState
,
10332 aForceReuseInnerWindow
);
10335 //*****************************************************************************
10336 // nsGlobalWindow: Creator Function (This should go away)
10337 //*****************************************************************************
10340 NS_NewScriptGlobalObject(PRBool aIsChrome
, PRBool aIsModalContentWindow
,
10341 nsIScriptGlobalObject
**aResult
)
10345 nsGlobalWindow
*global
;
10348 global
= new nsGlobalChromeWindow(nsnull
);
10349 } else if (aIsModalContentWindow
) {
10350 global
= new nsGlobalModalWindow(nsnull
);
10352 global
= new nsGlobalWindow(nsnull
);
10355 NS_ENSURE_TRUE(global
, NS_ERROR_OUT_OF_MEMORY
);
10357 NS_ADDREF(*aResult
= global
);
10362 //*****************************************************************************
10363 //*** nsNavigator: Object Management
10364 //*****************************************************************************
10366 nsNavigator::nsNavigator(nsIDocShell
*aDocShell
)
10367 : mDocShell(aDocShell
)
10371 nsNavigator::~nsNavigator()
10374 mMimeTypes
->Invalidate();
10376 mPlugins
->Invalidate();
10379 //*****************************************************************************
10380 // nsNavigator::nsISupports
10381 //*****************************************************************************
10384 DOMCI_DATA(Navigator
, nsNavigator
)
10386 // QueryInterface implementation for nsNavigator
10387 NS_INTERFACE_MAP_BEGIN(nsNavigator
)
10388 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMNavigator
)
10389 NS_INTERFACE_MAP_ENTRY(nsIDOMNavigator
)
10390 NS_INTERFACE_MAP_ENTRY(nsIDOMClientInformation
)
10391 NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorGeolocation
)
10392 NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorDesktopNotification
)
10393 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Navigator
)
10394 NS_INTERFACE_MAP_END
10397 NS_IMPL_ADDREF(nsNavigator
)
10398 NS_IMPL_RELEASE(nsNavigator
)
10402 nsNavigator::SetDocShell(nsIDocShell
*aDocShell
)
10404 mDocShell
= aDocShell
;
10406 mPlugins
->SetDocShell(aDocShell
);
10408 // if there is a page transition, make sure delete the geolocation object
10411 mGeolocation
->Shutdown();
10412 mGeolocation
= nsnull
;
10417 mNotification
->Shutdown();
10418 mNotification
= nsnull
;
10422 //*****************************************************************************
10423 // nsNavigator::nsIDOMNavigator
10424 //*****************************************************************************
10427 NS_GetNavigatorUserAgent(nsAString
& aUserAgent
)
10430 nsCOMPtr
<nsIHttpProtocolHandler
>
10431 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10432 if (NS_SUCCEEDED(rv
)) {
10434 rv
= service
->GetUserAgent(ua
);
10435 CopyASCIItoUTF16(ua
, aUserAgent
);
10442 NS_GetNavigatorPlatform(nsAString
& aPlatform
)
10444 if (!nsContentUtils::IsCallerTrustedForRead()) {
10445 const nsAdoptingCString
& override
=
10446 nsContentUtils::GetCharPref("general.platform.override");
10449 CopyUTF8toUTF16(override
, aPlatform
);
10455 nsCOMPtr
<nsIHttpProtocolHandler
>
10456 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10457 if (NS_SUCCEEDED(rv
)) {
10458 // sorry for the #if platform ugliness, but Communicator is
10459 // likewise hardcoded and we're seeking backward compatibility
10460 // here (bug 47080)
10461 #if defined(_WIN64)
10462 aPlatform
.AssignLiteral("Win64");
10463 #elif defined(WIN32)
10464 aPlatform
.AssignLiteral("Win32");
10465 #elif defined(XP_MACOSX) && defined(__ppc__)
10466 aPlatform
.AssignLiteral("MacPPC");
10467 #elif defined(XP_MACOSX) && defined(__i386__)
10468 aPlatform
.AssignLiteral("MacIntel");
10469 #elif defined(XP_MACOSX) && defined(__x86_64__)
10470 aPlatform
.AssignLiteral("MacIntel");
10471 #elif defined(XP_OS2)
10472 aPlatform
.AssignLiteral("OS/2");
10474 // XXX Communicator uses compiled-in build-time string defines
10475 // to indicate the platform it was compiled *for*, not what it is
10476 // currently running *on* which is what this does.
10477 nsCAutoString plat
;
10478 rv
= service
->GetOscpu(plat
);
10479 CopyASCIItoUTF16(plat
, aPlatform
);
10486 NS_GetNavigatorAppVersion(nsAString
& aAppVersion
)
10488 if (!nsContentUtils::IsCallerTrustedForRead()) {
10489 const nsAdoptingCString
& override
=
10490 nsContentUtils::GetCharPref("general.appversion.override");
10493 CopyUTF8toUTF16(override
, aAppVersion
);
10499 nsCOMPtr
<nsIHttpProtocolHandler
>
10500 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10501 if (NS_SUCCEEDED(rv
)) {
10503 rv
= service
->GetAppVersion(str
);
10504 CopyASCIItoUTF16(str
, aAppVersion
);
10508 aAppVersion
.AppendLiteral(" (");
10510 rv
= service
->GetPlatform(str
);
10514 AppendASCIItoUTF16(str
, aAppVersion
);
10516 aAppVersion
.Append(PRUnichar(')'));
10523 NS_GetNavigatorAppName(nsAString
& aAppName
)
10525 if (!nsContentUtils::IsCallerTrustedForRead()) {
10526 const nsAdoptingCString
& override
=
10527 nsContentUtils::GetCharPref("general.appname.override");
10530 CopyUTF8toUTF16(override
, aAppName
);
10535 aAppName
.AssignLiteral("Netscape");
10540 nsNavigator::GetUserAgent(nsAString
& aUserAgent
)
10542 return NS_GetNavigatorUserAgent(aUserAgent
);
10546 nsNavigator::GetAppCodeName(nsAString
& aAppCodeName
)
10549 nsCOMPtr
<nsIHttpProtocolHandler
>
10550 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10551 if (NS_SUCCEEDED(rv
)) {
10552 nsCAutoString appName
;
10553 rv
= service
->GetAppName(appName
);
10554 CopyASCIItoUTF16(appName
, aAppCodeName
);
10561 nsNavigator::GetAppVersion(nsAString
& aAppVersion
)
10563 return NS_GetNavigatorAppVersion(aAppVersion
);
10567 nsNavigator::GetAppName(nsAString
& aAppName
)
10569 return NS_GetNavigatorAppName(aAppName
);
10573 nsNavigator::GetLanguage(nsAString
& aLanguage
)
10576 nsCOMPtr
<nsIHttpProtocolHandler
>
10577 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10578 if (NS_SUCCEEDED(rv
)) {
10579 nsCAutoString lang
;
10580 rv
= service
->GetLanguage(lang
);
10581 CopyASCIItoUTF16(lang
, aLanguage
);
10588 nsNavigator::GetPlatform(nsAString
& aPlatform
)
10590 return NS_GetNavigatorPlatform(aPlatform
);
10594 nsNavigator::GetOscpu(nsAString
& aOSCPU
)
10596 if (!nsContentUtils::IsCallerTrustedForRead()) {
10597 const nsAdoptingCString
& override
=
10598 nsContentUtils::GetCharPref("general.oscpu.override");
10601 CopyUTF8toUTF16(override
, aOSCPU
);
10607 nsCOMPtr
<nsIHttpProtocolHandler
>
10608 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10609 if (NS_SUCCEEDED(rv
)) {
10610 nsCAutoString oscpu
;
10611 rv
= service
->GetOscpu(oscpu
);
10612 CopyASCIItoUTF16(oscpu
, aOSCPU
);
10619 nsNavigator::GetVendor(nsAString
& aVendor
)
10621 aVendor
.Truncate();
10627 nsNavigator::GetVendorSub(nsAString
& aVendorSub
)
10629 aVendorSub
.Truncate();
10634 nsNavigator::GetProduct(nsAString
& aProduct
)
10637 nsCOMPtr
<nsIHttpProtocolHandler
>
10638 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10639 if (NS_SUCCEEDED(rv
)) {
10640 nsCAutoString product
;
10641 rv
= service
->GetProduct(product
);
10642 CopyASCIItoUTF16(product
, aProduct
);
10649 nsNavigator::GetProductSub(nsAString
& aProductSub
)
10651 if (!nsContentUtils::IsCallerTrustedForRead()) {
10652 const nsAdoptingCString
& override
=
10653 nsContentUtils::GetCharPref("general.productSub.override");
10656 CopyUTF8toUTF16(override
, aProductSub
);
10659 // 'general.useragent.productSub' backwards compatible with 1.8 branch.
10660 const nsAdoptingCString
& override2
=
10661 nsContentUtils::GetCharPref("general.useragent.productSub");
10664 CopyUTF8toUTF16(override2
, aProductSub
);
10671 nsCOMPtr
<nsIHttpProtocolHandler
>
10672 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10673 if (NS_SUCCEEDED(rv
)) {
10674 nsCAutoString productSub
;
10675 rv
= service
->GetProductSub(productSub
);
10676 CopyASCIItoUTF16(productSub
, aProductSub
);
10683 nsNavigator::GetSecurityPolicy(nsAString
& aSecurityPolicy
)
10689 nsNavigator::GetMimeTypes(nsIDOMMimeTypeArray
**aMimeTypes
)
10692 mMimeTypes
= new nsMimeTypeArray(this);
10694 return NS_ERROR_OUT_OF_MEMORY
;
10698 NS_ADDREF(*aMimeTypes
= mMimeTypes
);
10704 nsNavigator::GetPlugins(nsIDOMPluginArray
**aPlugins
)
10707 mPlugins
= new nsPluginArray(this, mDocShell
);
10709 return NS_ERROR_OUT_OF_MEMORY
;
10713 NS_ADDREF(*aPlugins
= mPlugins
);
10718 // values for the network.cookie.cookieBehavior pref are documented in
10719 // nsCookieService.cpp.
10720 #define COOKIE_BEHAVIOR_REJECT 2
10723 nsNavigator::GetCookieEnabled(PRBool
*aCookieEnabled
)
10726 (nsContentUtils::GetIntPref("network.cookie.cookieBehavior",
10727 COOKIE_BEHAVIOR_REJECT
) !=
10728 COOKIE_BEHAVIOR_REJECT
);
10734 nsNavigator::GetOnLine(PRBool
* aOnline
)
10736 NS_PRECONDITION(aOnline
, "Null out param");
10738 *aOnline
= !NS_IsOffline();
10743 nsNavigator::GetBuildID(nsAString
& aBuildID
)
10745 if (!nsContentUtils::IsCallerTrustedForRead()) {
10746 const nsAdoptingCString
& override
=
10747 nsContentUtils::GetCharPref("general.buildID.override");
10750 CopyUTF8toUTF16(override
, aBuildID
);
10755 nsCOMPtr
<nsIXULAppInfo
> appInfo
=
10756 do_GetService("@mozilla.org/xre/app-info;1");
10758 return NS_ERROR_NOT_IMPLEMENTED
;
10760 nsCAutoString buildID
;
10761 nsresult rv
= appInfo
->GetAppBuildID(buildID
);
10765 aBuildID
.Truncate();
10766 AppendASCIItoUTF16(buildID
, aBuildID
);
10771 nsNavigator::JavaEnabled(PRBool
*aReturn
)
10773 // Return true if we have a handler for "application/x-java-vm",
10774 // otherwise return false.
10775 *aReturn
= PR_FALSE
;
10778 mMimeTypes
= new nsMimeTypeArray(this);
10780 return NS_ERROR_OUT_OF_MEMORY
;
10783 RefreshMIMEArray();
10786 mMimeTypes
->GetLength(&count
);
10787 for (PRUint32 i
= 0; i
< count
; i
++) {
10789 nsIDOMMimeType
* type
= mMimeTypes
->GetItemAt(i
, &rv
);
10790 nsAutoString mimeString
;
10791 if (type
&& NS_SUCCEEDED(type
->GetType(mimeString
))) {
10792 if (mimeString
.EqualsLiteral("application/x-java-vm")) {
10793 *aReturn
= PR_TRUE
;
10803 nsNavigator::TaintEnabled(PRBool
*aReturn
)
10805 *aReturn
= PR_FALSE
;
10810 nsNavigator::LoadingNewDocument()
10812 // Release these so that they will be recreated for the
10813 // new document (if requested). The plugins or mime types
10814 // arrays may have changed. See bug 150087.
10816 mMimeTypes
->Invalidate();
10817 mMimeTypes
= nsnull
;
10821 mPlugins
->Invalidate();
10827 mGeolocation
->Shutdown();
10828 mGeolocation
= nsnull
;
10833 mNotification
->Shutdown();
10834 mNotification
= nsnull
;
10840 nsNavigator::RefreshMIMEArray()
10842 nsresult rv
= NS_OK
;
10844 rv
= mMimeTypes
->Refresh();
10849 nsNavigator::HasDesktopNotificationSupport()
10851 return nsContentUtils::GetBoolPref("notification.feature.enabled", PR_FALSE
);
10854 //*****************************************************************************
10855 // nsNavigator::nsIDOMClientInformation
10856 //*****************************************************************************
10859 nsNavigator::RegisterContentHandler(const nsAString
& aMIMEType
,
10860 const nsAString
& aURI
,
10861 const nsAString
& aTitle
)
10863 nsCOMPtr
<nsIWebContentHandlerRegistrar
> registrar
=
10864 do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID
);
10865 if (registrar
&& mDocShell
) {
10866 nsCOMPtr
<nsIDOMWindow
> contentDOMWindow(do_GetInterface(mDocShell
));
10867 if (contentDOMWindow
)
10868 return registrar
->RegisterContentHandler(aMIMEType
, aURI
, aTitle
,
10876 nsNavigator::RegisterProtocolHandler(const nsAString
& aProtocol
,
10877 const nsAString
& aURI
,
10878 const nsAString
& aTitle
)
10880 nsCOMPtr
<nsIWebContentHandlerRegistrar
> registrar
=
10881 do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID
);
10882 if (registrar
&& mDocShell
) {
10883 nsCOMPtr
<nsIDOMWindow
> contentDOMWindow(do_GetInterface(mDocShell
));
10884 if (contentDOMWindow
)
10885 return registrar
->RegisterProtocolHandler(aProtocol
, aURI
, aTitle
,
10894 nsNavigator::MozIsLocallyAvailable(const nsAString
&aURI
,
10895 PRBool aWhenOffline
,
10896 PRBool
*aIsAvailable
)
10898 nsCOMPtr
<nsIURI
> uri
;
10899 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aURI
);
10900 NS_ENSURE_SUCCESS(rv
, rv
);
10902 // This method of checking the cache will only work for http/https urls
10904 rv
= uri
->SchemeIs("http", &match
);
10905 NS_ENSURE_SUCCESS(rv
, rv
);
10907 rv
= uri
->SchemeIs("https", &match
);
10908 NS_ENSURE_SUCCESS(rv
, rv
);
10909 if (!match
) return NS_ERROR_DOM_BAD_URI
;
10912 // Same origin check
10913 nsCOMPtr
<nsIJSContextStack
> stack
= do_GetService(sJSStackContractID
);
10914 NS_ENSURE_TRUE(stack
, NS_ERROR_FAILURE
);
10916 JSContext
*cx
= nsnull
;
10917 rv
= stack
->Peek(&cx
);
10918 NS_ENSURE_TRUE(cx
, NS_ERROR_FAILURE
);
10920 rv
= nsContentUtils::GetSecurityManager()->CheckSameOrigin(cx
, uri
);
10921 NS_ENSURE_SUCCESS(rv
, rv
);
10923 // these load flags cause an error to be thrown if there is no
10924 // valid cache entry, and skip the load if there is.
10925 // if the cache is busy, assume that it is not yet available rather
10926 // than waiting for it to become available.
10927 PRUint32 loadFlags
= nsIChannel::INHIBIT_CACHING
|
10928 nsICachingChannel::LOAD_NO_NETWORK_IO
|
10929 nsICachingChannel::LOAD_ONLY_IF_MODIFIED
|
10930 nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY
;
10932 if (aWhenOffline
) {
10933 loadFlags
|= nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE
|
10934 nsICachingChannel::LOAD_ONLY_FROM_CACHE
|
10935 nsIRequest::LOAD_FROM_CACHE
;
10938 nsCOMPtr
<nsIChannel
> channel
;
10939 rv
= NS_NewChannel(getter_AddRefs(channel
), uri
,
10940 nsnull
, nsnull
, nsnull
, loadFlags
);
10941 NS_ENSURE_SUCCESS(rv
, rv
);
10943 nsCOMPtr
<nsIInputStream
> stream
;
10944 rv
= channel
->Open(getter_AddRefs(stream
));
10945 NS_ENSURE_SUCCESS(rv
, rv
);
10950 rv
= channel
->GetStatus(&status
);
10951 NS_ENSURE_SUCCESS(rv
, rv
);
10953 if (NS_SUCCEEDED(status
)) {
10954 nsCOMPtr
<nsIHttpChannel
> httpChannel
= do_QueryInterface(channel
);
10955 rv
= httpChannel
->GetRequestSucceeded(aIsAvailable
);
10956 NS_ENSURE_SUCCESS(rv
, rv
);
10958 *aIsAvailable
= PR_FALSE
;
10964 //*****************************************************************************
10965 // nsNavigator::nsIDOMNavigatorGeolocation
10966 //*****************************************************************************
10968 NS_IMETHODIMP
nsNavigator::GetGeolocation(nsIDOMGeoGeolocation
**_retval
)
10970 NS_ENSURE_ARG_POINTER(_retval
);
10973 if (mGeolocation
) {
10974 NS_ADDREF(*_retval
= mGeolocation
);
10979 return NS_ERROR_FAILURE
;
10981 nsCOMPtr
<nsIDOMWindow
> contentDOMWindow(do_GetInterface(mDocShell
));
10982 if (!contentDOMWindow
)
10983 return NS_ERROR_FAILURE
;
10985 mGeolocation
= new nsGeolocation();
10987 return NS_ERROR_FAILURE
;
10989 if (NS_FAILED(mGeolocation
->Init(contentDOMWindow
)))
10990 return NS_ERROR_FAILURE
;
10992 NS_ADDREF(*_retval
= mGeolocation
);
10997 //*****************************************************************************
10998 // nsNavigator::nsIDOMNavigatorDesktopNotification
10999 //*****************************************************************************
11001 NS_IMETHODIMP
nsNavigator::GetMozNotification(nsIDOMDesktopNotificationCenter
**aRetVal
)
11003 NS_ENSURE_ARG_POINTER(aRetVal
);
11006 if (mNotification
) {
11007 NS_ADDREF(*aRetVal
= mNotification
);
11011 nsCOMPtr
<nsPIDOMWindow
> window(do_GetInterface(mDocShell
));
11012 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
11014 nsCOMPtr
<nsIDocument
> document
= do_GetInterface(mDocShell
);
11015 NS_ENSURE_TRUE(document
, NS_ERROR_FAILURE
);
11017 nsIScriptGlobalObject
*sgo
= document
->GetScopeObject();
11018 NS_ENSURE_TRUE(sgo
, NS_ERROR_FAILURE
);
11020 nsIScriptContext
*scx
= sgo
->GetContext();
11021 NS_ENSURE_TRUE(scx
, NS_ERROR_FAILURE
);
11023 mNotification
= new nsDesktopNotificationCenter(window
->GetCurrentInnerWindow(),
11025 if (!mNotification
) {
11026 return NS_ERROR_FAILURE
;
11029 NS_ADDREF(*aRetVal
= mNotification
);