1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=2 et tw=78: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
24 * Travis Bogard <travis@netscape.com>
25 * Brendan Eich <brendan@mozilla.org>
26 * David Hyatt (hyatt@netscape.com)
27 * Dan Rosen <dr@netscape.com>
28 * Vidur Apparao <vidur@netscape.com>
29 * Johnny Stenback <jst@netscape.com>
30 * Mark Hammond <mhammond@skippinet.com.au>
31 * Ryan Jones <sciguyryan@gmail.com>
32 * Jeff Walden <jwalden+code@mit.edu>
34 * Alternatively, the contents of this file may be used under the terms of
35 * either of the GNU General Public License Version 2 or later (the "GPL"),
36 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
37 * in which case the provisions of the GPL or the LGPL are applicable instead
38 * of those above. If you wish to allow use of your version of this file only
39 * under the terms of either the GPL or the LGPL, and not to allow others to
40 * use your version of this file under the terms of the MPL, indicate your
41 * decision by deleting the provisions above and replace them with the notice
42 * and other provisions required by the GPL or the LGPL. If you do not delete
43 * the provisions above, a recipient may use your version of this file under
44 * the terms of any one of the MPL, the GPL or the LGPL.
46 * ***** END LICENSE BLOCK ***** */
49 #include "base/basictypes.h"
53 #include "nsGlobalWindow.h"
55 #include "nsHistory.h"
56 #include "nsBarProps.h"
57 #include "nsDOMStorage.h"
58 #include "nsDOMOfflineResourceList.h"
59 #include "nsDOMError.h"
62 #include "nsXPIDLString.h"
63 #include "nsJSUtils.h"
65 #include "jsapi.h" // for JSAutoRequest
66 #include "jsdbgapi.h" // for JS_ClearWatchPointsForObject
67 #include "nsReadableUtils.h"
68 #include "nsDOMClassInfo.h"
69 #include "nsJSEnvironment.h"
72 #include "nsIEventListenerManager.h"
74 #include "nsStyleCoord.h"
75 #include "nsMimeTypeArray.h"
76 #include "nsNetUtil.h"
77 #include "nsICachingChannel.h"
78 #include "nsPluginArray.h"
79 #include "nsIPluginHost.h"
80 #include "nsGeolocation.h"
81 #include "nsDesktopNotification.h"
82 #include "nsContentCID.h"
83 #include "nsLayoutStatics.h"
84 #include "nsCycleCollector.h"
85 #include "nsCCUncollectableMarker.h"
86 #include "nsDOMThreadService.h"
87 #include "nsAutoJSValHolder.h"
91 #include "nsCanvasFrame.h"
92 #include "nsIWidget.h"
93 #include "nsIBaseWindow.h"
94 #include "nsAccelerometer.h"
95 #include "nsIContent.h"
96 #include "nsIContentViewerEdit.h"
97 #include "nsIDocShell.h"
98 #include "nsIDocShellLoadInfo.h"
99 #include "nsIDocShellTreeItem.h"
100 #include "nsIDocShellTreeNode.h"
101 #include "nsIEditorDocShell.h"
102 #include "nsIDocCharset.h"
103 #include "nsIDocument.h"
104 #include "nsIHTMLDocument.h"
105 #include "nsIDOMHTMLDocument.h"
106 #include "nsIDOMHTMLElement.h"
107 #ifndef MOZ_DISABLE_DOMCRYPTO
108 #include "nsIDOMCrypto.h"
110 #include "nsIDOMDocument.h"
111 #include "nsIDOM3Document.h"
112 #include "nsIDOMNSDocument.h"
113 #include "nsIDOMDocumentView.h"
114 #include "nsIDOMElement.h"
115 #include "nsIDOMDocumentEvent.h"
116 #include "nsIDOMEvent.h"
117 #include "nsIDOMHTMLAnchorElement.h"
118 #include "nsIDOMKeyEvent.h"
119 #include "nsIDOMMessageEvent.h"
120 #include "nsIDOMPopupBlockedEvent.h"
121 #include "nsIDOMPopStateEvent.h"
122 #include "nsIDOMPopStateEvent_MOZILLA_2_BRANCH.h"
123 #include "nsIDOMOfflineResourceList.h"
124 #include "nsIDOMGeoGeolocation.h"
125 #include "nsIDOMDesktopNotification.h"
126 #include "nsPIDOMStorage.h"
127 #include "nsDOMString.h"
128 #include "nsIEmbeddingSiteWindow2.h"
129 #include "nsThreadUtils.h"
130 #include "nsIEventStateManager.h"
131 #include "nsIHttpProtocolHandler.h"
132 #include "nsIJSContextStack.h"
133 #include "nsIJSRuntimeService.h"
134 #include "nsIMarkupDocumentViewer.h"
135 #include "nsIPrefBranch.h"
136 #include "nsIPresShell.h"
137 #include "nsIPrivateDOMEvent.h"
138 #include "nsIProgrammingLanguage.h"
139 #include "nsIServiceManager.h"
140 #include "nsIScriptGlobalObjectOwner.h"
141 #include "nsIScriptSecurityManager.h"
142 #include "nsIScrollableFrame.h"
144 #include "nsIViewManager.h"
145 #include "nsISelectionController.h"
146 #include "nsISelection.h"
147 #include "nsIPrompt.h"
148 #include "nsIPromptService.h"
149 #include "nsIPromptFactory.h"
150 #include "nsIWritablePropertyBag2.h"
151 #include "nsIWebNavigation.h"
152 #include "nsIWebBrowser.h"
153 #include "nsIWebBrowserChrome.h"
154 #include "nsIWebBrowserFind.h" // For window.find()
155 #include "nsIWebContentHandlerRegistrar.h"
156 #include "nsIWindowMediator.h" // For window.find()
157 #include "nsComputedDOMStyle.h"
158 #include "nsIEntropyCollector.h"
159 #include "nsDOMCID.h"
160 #include "nsDOMError.h"
161 #include "nsDOMWindowUtils.h"
162 #include "nsIWindowWatcher.h"
163 #include "nsPIWindowWatcher.h"
164 #include "nsIContentViewer.h"
165 #include "nsDOMClassInfo.h"
166 #include "nsIJSNativeInitializer.h"
167 #include "nsIScriptError.h"
168 #include "nsIScriptEventManager.h" // For GetInterface()
169 #include "nsIConsoleService.h"
170 #include "nsIControllers.h"
171 #include "nsIControllerContext.h"
172 #include "nsGlobalWindowCommands.h"
173 #include "nsAutoPtr.h"
174 #include "nsContentUtils.h"
175 #include "nsCSSProps.h"
176 #include "nsFileDataProtocolHandler.h"
177 #include "nsIDOMFile.h"
178 #include "nsIURIFixup.h"
179 #include "mozilla/FunctionTimer.h"
180 #include "nsCDefaultURIFixup.h"
181 #include "nsEventDispatcher.h"
182 #include "nsIObserverService.h"
183 #include "nsIXULAppInfo.h"
184 #include "nsNetUtil.h"
185 #include "nsFocusManager.h"
186 #include "nsIXULWindow.h"
187 #include "nsEventStateManager.h"
189 #include "nsXULPopupManager.h"
190 #include "nsIDOMXULControlElement.h"
191 #include "nsIFrame.h"
194 #include "xpcprivate.h"
197 #include "nsIPrintSettings.h"
198 #include "nsIPrintSettingsService.h"
199 #include "nsIWebBrowserPrint.h"
202 #include "nsWindowRoot.h"
203 #include "nsNetCID.h"
204 #include "nsIArray.h"
205 #include "nsIScriptRuntime.h"
207 // XXX An unfortunate dependency exists here (two XUL files).
208 #include "nsIDOMXULDocument.h"
209 #include "nsIDOMXULCommandDispatcher.h"
211 #include "nsBindingManager.h"
212 #include "nsIXBLService.h"
214 // used for popup blocking, needs to be converted to something
215 // belonging to the back-end like nsIContentPolicy
216 #include "nsIPopupWindowManager.h"
218 #include "nsIDragService.h"
219 #include "mozilla/dom/Element.h"
220 #include "nsFrameLoader.h"
221 #include "nsISupportsPrimitives.h"
222 #include "nsXPCOMCID.h"
224 #include "mozilla/FunctionTimer.h"
225 #include "mozIThirdPartyUtil.h"
228 // so we can get logging even in release builds
229 #define FORCE_PR_LOG 1
233 #include "mozilla/dom/indexedDB/IDBFactory.h"
234 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
236 #include "nsRefreshDriver.h"
239 static PRLogModuleInfo
* gDOMLeakPRLog
;
242 static const char kStorageEnabled
[] = "dom.storage.enabled";
244 using namespace mozilla::dom
;
245 using mozilla::TimeStamp
;
246 using mozilla::TimeDuration
;
248 nsIDOMStorageList
*nsGlobalWindow::sGlobalStorageList
= nsnull
;
249 nsGlobalWindow::WindowByIdTable
*nsGlobalWindow::sOuterWindowsById
= nsnull
;
251 static nsIEntropyCollector
*gEntropyCollector
= nsnull
;
252 static PRInt32 gRefCnt
= 0;
253 static PRInt32 gOpenPopupSpamCount
= 0;
254 static PopupControlState gPopupControlState
= openAbused
;
255 static PRInt32 gRunningTimeoutDepth
= 0;
256 static PRPackedBool gMouseDown
= PR_FALSE
;
257 static PRPackedBool gDragServiceDisabled
= PR_FALSE
;
258 static FILE *gDumpFile
= nsnull
;
259 static PRUint64 gNextWindowID
= 0;
260 static PRUint32 gSerialCounter
= 0;
263 PRInt32 gTimeoutCnt
= 0;
266 #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
267 static PRBool gDOMWindowDumpEnabled
= PR_FALSE
;
270 #if defined(DEBUG_bryner) || defined(DEBUG_chb)
271 #define DEBUG_PAGE_CACHE
274 // The default shortest interval/timeout we permit
275 #define DEFAULT_MIN_TIMEOUT_VALUE 10 // 10ms
276 static PRInt32 gMinTimeoutValue
;
277 static inline PRInt32
DOMMinTimeoutValue() {
278 return NS_MAX(gMinTimeoutValue
, 0);
281 // The number of nested timeouts before we start clamping. HTML5 says 1, WebKit
283 #define DOM_CLAMP_TIMEOUT_NESTING_LEVEL 5
285 // The longest interval (as PRIntervalTime) we permit, or that our
286 // timer code can handle, really. See DELAY_INTERVAL_LIMIT in
287 // nsTimerImpl.h for details.
288 #define DOM_MAX_TIMEOUT_VALUE PR_BIT(8 * sizeof(PRIntervalTime) - 1)
290 #define FORWARD_TO_OUTER(method, args, err_rval) \
292 if (IsInnerWindow()) { \
293 nsGlobalWindow *outer = GetOuterWindowInternal(); \
295 NS_WARNING("No outer window available!"); \
298 return outer->method args; \
302 #define FORWARD_TO_OUTER_VOID(method, args) \
304 if (IsInnerWindow()) { \
305 nsGlobalWindow *outer = GetOuterWindowInternal(); \
307 NS_WARNING("No outer window available!"); \
310 outer->method args; \
315 #define FORWARD_TO_OUTER_CHROME(method, args, err_rval) \
317 if (IsInnerWindow()) { \
318 nsGlobalWindow *outer = GetOuterWindowInternal(); \
320 NS_WARNING("No outer window available!"); \
323 return ((nsGlobalChromeWindow *)outer)->method args; \
327 #define FORWARD_TO_INNER_CHROME(method, args, err_rval) \
329 if (IsOuterWindow()) { \
330 if (!mInnerWindow) { \
331 NS_WARNING("No inner window available!"); \
334 return ((nsGlobalChromeWindow *)mInnerWindow)->method args; \
338 #define FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(method, args, err_rval) \
340 if (IsInnerWindow()) { \
341 nsGlobalWindow *outer = GetOuterWindowInternal(); \
343 NS_WARNING("No outer window available!"); \
346 return ((nsGlobalModalWindow *)outer)->method args; \
350 #define FORWARD_TO_INNER(method, args, err_rval) \
352 if (IsOuterWindow()) { \
353 if (!mInnerWindow) { \
354 NS_WARNING("No inner window available!"); \
357 return GetCurrentInnerWindowInternal()->method args; \
361 #define FORWARD_TO_INNER_MODAL_CONTENT_WINDOW(method, args, err_rval) \
363 if (IsOuterWindow()) { \
364 if (!mInnerWindow) { \
365 NS_WARNING("No inner window available!"); \
368 return ((nsGlobalModalWindow*)GetCurrentInnerWindowInternal())->method args; \
372 #define FORWARD_TO_INNER_VOID(method, args) \
374 if (IsOuterWindow()) { \
375 if (!mInnerWindow) { \
376 NS_WARNING("No inner window available!"); \
379 GetCurrentInnerWindowInternal()->method args; \
384 // Same as FORWARD_TO_INNER, but this will create a fresh inner if an
385 // inner doesn't already exists.
386 #define FORWARD_TO_INNER_CREATE(method, args, err_rval) \
388 if (IsOuterWindow()) { \
389 if (!mInnerWindow) { \
393 nsCOMPtr<nsIDOMDocument> doc; \
394 nsresult fwdic_nr = GetDocument(getter_AddRefs(doc)); \
395 NS_ENSURE_SUCCESS(fwdic_nr, err_rval); \
396 if (!mInnerWindow) { \
400 return GetCurrentInnerWindowInternal()->method args; \
405 static NS_DEFINE_CID(kXULControllersCID
, NS_XULCONTROLLERS_CID
);
407 static const char sJSStackContractID
[] = "@mozilla.org/js/xpc/ContextStack;1";
408 #ifndef MOZ_DISABLE_DOMCRYPTO
409 static const char kCryptoContractID
[] = NS_CRYPTO_CONTRACTID
;
410 static const char kPkcs11ContractID
[] = NS_PKCS11_CONTRACTID
;
412 static const char sPopStatePrefStr
[] = "browser.history.allowPopState";
415 IsAboutBlank(nsIURI
* aURI
)
417 NS_PRECONDITION(aURI
, "Must have URI");
419 // GetSpec can be expensive for some URIs, so check the scheme first.
420 PRBool isAbout
= PR_FALSE
;
421 if (NS_FAILED(aURI
->SchemeIs("about", &isAbout
)) || !isAbout
) {
427 return str
.EqualsLiteral("about:blank");
430 class nsDummyJavaPluginOwner
: public nsIPluginInstanceOwner
433 nsDummyJavaPluginOwner(nsIDocument
*aDocument
)
434 : mDocument(aDocument
)
440 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
441 NS_DECL_NSIPLUGININSTANCEOWNER
443 NS_IMETHOD
GetURL(const char *aURL
, const char *aTarget
,
444 nsIInputStream
*aPostStream
,
445 void *aHeadersData
, PRUint32 aHeadersDataLen
);
446 NS_IMETHOD
ShowStatus(const PRUnichar
*aStatusMsg
);
447 NPError
ShowNativeContextMenu(NPMenu
* menu
, void* event
);
448 NPBool
ConvertPoint(double sourceX
, double sourceY
, NPCoordinateSpace sourceSpace
,
449 double *destX
, double *destY
, NPCoordinateSpace destSpace
);
450 void SendIdleEvent();
452 NS_DECL_CYCLE_COLLECTION_CLASS(nsDummyJavaPluginOwner
)
455 nsCOMPtr
<nsIPluginInstance
> mInstance
;
456 nsCOMPtr
<nsIDocument
> mDocument
;
459 NS_IMPL_CYCLE_COLLECTION_2(nsDummyJavaPluginOwner
, mDocument
, mInstance
)
461 // QueryInterface implementation for nsDummyJavaPluginOwner
462 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDummyJavaPluginOwner
)
463 NS_INTERFACE_MAP_ENTRY(nsISupports
)
464 NS_INTERFACE_MAP_ENTRY(nsIPluginInstanceOwner
)
467 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDummyJavaPluginOwner
)
468 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDummyJavaPluginOwner
)
472 nsDummyJavaPluginOwner::Destroy()
474 // If we have a plugin instance, stop it and destroy it now.
477 mInstance
->InvalidateOwner();
485 nsDummyJavaPluginOwner::SetInstance(nsIPluginInstance
*aInstance
)
487 // If we're going to null out mInstance after use, be sure to call
488 // mInstance->InvalidateOwner() here, since it now won't be called
489 // from nsDummyJavaPluginOwner::Destroy().
490 if (mInstance
&& !aInstance
)
491 mInstance
->InvalidateOwner();
493 mInstance
= aInstance
;
499 nsDummyJavaPluginOwner::GetInstance(nsIPluginInstance
*&aInstance
)
501 NS_IF_ADDREF(aInstance
= mInstance
);
507 nsDummyJavaPluginOwner::GetWindow(NPWindow
*&aWindow
)
515 nsDummyJavaPluginOwner::GetMode(PRInt32
*aMode
)
517 // This is wrong, but there's no better alternative.
520 return NS_ERROR_NOT_IMPLEMENTED
;
524 nsDummyJavaPluginOwner::CreateWidget(void)
526 return NS_ERROR_NOT_IMPLEMENTED
;
530 nsDummyJavaPluginOwner::GetURL(const char *aURL
, const char *aTarget
,
531 nsIInputStream
*aPostStream
,
532 void *aHeadersData
, PRUint32 aHeadersDataLen
)
534 return NS_ERROR_NOT_IMPLEMENTED
;
538 nsDummyJavaPluginOwner::ShowStatus(const char *aStatusMsg
)
540 return NS_ERROR_NOT_IMPLEMENTED
;
544 nsDummyJavaPluginOwner::ShowStatus(const PRUnichar
*aStatusMsg
)
546 return NS_ERROR_NOT_IMPLEMENTED
;
550 nsDummyJavaPluginOwner::ShowNativeContextMenu(NPMenu
* menu
, void* event
)
552 return NPERR_GENERIC_ERROR
;
556 nsDummyJavaPluginOwner::ConvertPoint(double sourceX
, double sourceY
, NPCoordinateSpace sourceSpace
,
557 double *destX
, double *destY
, NPCoordinateSpace destSpace
)
563 nsDummyJavaPluginOwner::GetDocument(nsIDocument
**aDocument
)
565 NS_IF_ADDREF(*aDocument
= mDocument
);
571 nsDummyJavaPluginOwner::InvalidateRect(NPRect
*invalidRect
)
573 return NS_ERROR_NOT_IMPLEMENTED
;
577 nsDummyJavaPluginOwner::InvalidateRegion(NPRegion invalidRegion
)
579 return NS_ERROR_NOT_IMPLEMENTED
;
583 nsDummyJavaPluginOwner::ForceRedraw()
585 return NS_ERROR_NOT_IMPLEMENTED
;
589 nsDummyJavaPluginOwner::GetNetscapeWindow(void *value
)
591 return NS_ERROR_NOT_IMPLEMENTED
;
595 nsDummyJavaPluginOwner::SetEventModel(PRInt32 eventModel
)
597 return NS_ERROR_NOT_IMPLEMENTED
;
601 nsDummyJavaPluginOwner::SendIdleEvent()
606 * An object implementing the window.URL property.
608 class nsDOMMozURLProperty
: public nsIDOMMozURLProperty
611 nsDOMMozURLProperty(nsGlobalWindow
* aWindow
)
617 NS_DECL_NSIDOMMOZURLPROPERTY
619 void ClearWindowReference() {
623 nsGlobalWindow
* mWindow
;
626 DOMCI_DATA(MozURLProperty
, nsDOMMozURLProperty
)
627 NS_IMPL_ADDREF(nsDOMMozURLProperty
)
628 NS_IMPL_RELEASE(nsDOMMozURLProperty
)
629 NS_INTERFACE_MAP_BEGIN(nsDOMMozURLProperty
)
630 NS_INTERFACE_MAP_ENTRY(nsIDOMMozURLProperty
)
631 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMMozURLProperty
)
632 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozURLProperty
)
636 nsDOMMozURLProperty::CreateObjectURL(nsIDOMBlob
* aBlob
, nsAString
& aURL
)
638 NS_PRECONDITION(!mWindow
|| mWindow
->IsInnerWindow(),
639 "Should be inner window");
641 NS_ENSURE_STATE(mWindow
&& mWindow
->mDoc
);
642 NS_ENSURE_ARG_POINTER(aBlob
);
644 nsIDocument
* doc
= mWindow
->mDoc
;
646 nsresult rv
= aBlob
->GetInternalUrl(doc
->NodePrincipal(), aURL
);
647 NS_ENSURE_SUCCESS(rv
, rv
);
649 doc
->RegisterFileDataUri(NS_LossyConvertUTF16toASCII(aURL
));
655 nsDOMMozURLProperty::RevokeObjectURL(const nsAString
& aURL
)
657 NS_PRECONDITION(!mWindow
|| mWindow
->IsInnerWindow(),
658 "Should be inner window");
660 NS_ENSURE_STATE(mWindow
);
662 NS_LossyConvertUTF16toASCII
asciiurl(aURL
);
664 nsIPrincipal
* winPrincipal
= mWindow
->GetPrincipal();
669 nsIPrincipal
* principal
=
670 nsFileDataProtocolHandler::GetFileDataEntryPrincipal(asciiurl
);
672 if (principal
&& winPrincipal
&&
673 NS_SUCCEEDED(winPrincipal
->Subsumes(principal
, &subsumes
)) &&
676 mWindow
->mDoc
->UnregisterFileDataUri(asciiurl
);
678 nsFileDataProtocolHandler::RemoveFileDataEntry(asciiurl
);
685 * An indirect observer object that means we don't have to implement nsIObserver
686 * on nsGlobalWindow, where any script could see it.
688 class nsGlobalWindowObserver
: public nsIObserver
{
690 nsGlobalWindowObserver(nsGlobalWindow
* aWindow
) : mWindow(aWindow
) {}
692 NS_IMETHOD
Observe(nsISupports
* aSubject
, const char* aTopic
, const PRUnichar
* aData
)
696 return mWindow
->Observe(aSubject
, aTopic
, aData
);
698 void Forget() { mWindow
= nsnull
; }
700 nsGlobalWindow
* mWindow
;
703 NS_IMPL_ISUPPORTS1(nsGlobalWindowObserver
, nsIObserver
)
705 nsTimeout::nsTimeout()
709 extern int gTimeoutCnt
;
715 memset(this, 0, sizeof(*this));
717 MOZ_COUNT_CTOR(nsTimeout
);
720 nsTimeout::~nsTimeout()
724 extern int gTimeoutCnt
;
730 MOZ_COUNT_DTOR(nsTimeout
);
733 NS_IMPL_CYCLE_COLLECTION_CLASS(nsTimeout
)
734 NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsTimeout
)
735 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsTimeout
)
736 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mWindow
,
737 nsIScriptGlobalObject
)
738 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrincipal
)
739 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptHandler
)
740 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
741 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTimeout
, AddRef
)
742 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsTimeout
, Release
)
744 nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow
*aOuterWindow
)
745 : mFrameElement(nsnull
), mDocShell(nsnull
), mModalStateDepth(0),
746 mRunningTimeout(nsnull
), mMutationBits(0), mIsDocumentLoaded(PR_FALSE
),
747 mIsHandlingResizeEvent(PR_FALSE
), mIsInnerWindow(aOuterWindow
!= nsnull
),
748 mMayHavePaintEventListener(PR_FALSE
), mMayHaveTouchEventListener(PR_FALSE
),
749 mMayHaveAudioAvailableEventListener(PR_FALSE
), mIsModalContentWindow(PR_FALSE
),
750 mIsActive(PR_FALSE
), mInnerWindow(nsnull
), mOuterWindow(aOuterWindow
),
751 // Make sure no actual window ends up with mWindowID == 0
752 mWindowID(++gNextWindowID
), mHasNotifiedGlobalCreated(PR_FALSE
)
755 nsPIDOMWindow::~nsPIDOMWindow() {}
757 //*****************************************************************************
758 // nsOuterWindowProxy: Outer Window Proxy
759 //*****************************************************************************
762 nsOuterWindowProxy::obj_toString(JSContext
*cx
, JSObject
*proxy
)
764 JS_ASSERT(proxy
->isProxy());
766 return JS_NewStringCopyZ(cx
, "[object Window]");
770 nsOuterWindowProxy::singleton
;
773 NS_NewOuterWindowProxy(JSContext
*cx
, JSObject
*parent
)
775 JSAutoEnterCompartment ac
;
776 if (!ac
.enter(cx
, parent
)) {
780 JSObject
*obj
= JSWrapper::New(cx
, parent
, parent
->getProto(), parent
,
781 &nsOuterWindowProxy::singleton
);
782 NS_ASSERTION(obj
->getClass()->ext
.innerObject
, "bad class");
786 //*****************************************************************************
787 //*** nsGlobalWindow: Object Management
788 //*****************************************************************************
790 nsGlobalWindow::nsGlobalWindow(nsGlobalWindow
*aOuterWindow
)
791 : nsPIDOMWindow(aOuterWindow
),
793 mDidInitJavaProperties(PR_FALSE
),
794 mFullScreen(PR_FALSE
),
797 mHavePendingClose(PR_FALSE
),
798 mHadOriginalOpener(PR_FALSE
),
799 mIsPopupSpam(PR_FALSE
),
800 mBlockScriptedClosingFlag(PR_FALSE
),
801 mFireOfflineStatusChangeEventOnThaw(PR_FALSE
),
802 mCreatingInnerWindow(PR_FALSE
),
804 mCleanMessageManager(PR_FALSE
),
805 mNeedsFocus(PR_TRUE
),
807 #if defined(XP_MAC) || defined(XP_MACOSX)
808 mShowAccelerators(PR_FALSE
),
809 mShowFocusRings(PR_FALSE
),
811 mShowAccelerators(PR_TRUE
),
812 mShowFocusRings(PR_TRUE
),
814 mShowFocusRingForContent(PR_FALSE
),
815 mFocusByKeyOccurred(PR_FALSE
),
816 mHasAcceleration(PR_FALSE
),
817 mNotifiedIDDestroyed(PR_FALSE
),
818 mTimeoutInsertionPoint(nsnull
),
819 mTimeoutPublicIdCounter(1),
820 mTimeoutFiringDepth(0),
822 mPendingStorageEventsObsolete(nsnull
),
823 mTimeoutsSuspendDepth(0),
827 mSetOpenerWindowCalled(PR_FALSE
),
829 mCleanedUp(PR_FALSE
),
830 mCallCleanUpAfterModalDialogCloses(PR_FALSE
),
831 mDialogAbuseCount(0),
832 mDialogDisabled(PR_FALSE
)
834 nsLayoutStatics::AddRef();
836 // Initialize the PRCList (this).
839 // Initialize timeout storage
840 PR_INIT_CLIST(&mTimeouts
);
843 // |this| is an inner window, add this inner window to the outer
844 // window list of inners.
845 PR_INSERT_AFTER(this, aOuterWindow
);
847 mObserver
= new nsGlobalWindowObserver(this);
849 NS_ADDREF(mObserver
);
850 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
852 // Watch for online/offline status changes so we can fire events. Use
853 // a strong reference.
854 os
->AddObserver(mObserver
, NS_IOSERVICE_OFFLINE_STATUS_TOPIC
,
857 // Watch for dom-storage-changed so we can fire storage
858 // events. Use a strong reference.
859 os
->AddObserver(mObserver
, "dom-storage2-changed", PR_FALSE
);
860 os
->AddObserver(mObserver
, "dom-storage-changed", PR_FALSE
);
864 // |this| is an outer window. Outer windows start out frozen and
865 // remain frozen until they get an inner window, so freeze this
866 // outer window here.
872 if (!sOuterWindowsById
) {
873 sOuterWindowsById
= new WindowByIdTable();
874 if (!sOuterWindowsById
->Init()) {
875 delete sOuterWindowsById
;
876 sOuterWindowsById
= nsnull
;
880 if (sOuterWindowsById
) {
881 sOuterWindowsById
->Put(mWindowID
, this);
885 // We could have failed the first time through trying
886 // to create the entropy collector, so we should
887 // try to get one until we succeed.
892 #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
893 nsContentUtils::AddBoolPrefVarCache("browser.dom.window.dump.enabled",
894 &gDOMWindowDumpEnabled
);
896 nsContentUtils::AddIntPrefVarCache("dom.min_timeout_value",
898 DEFAULT_MIN_TIMEOUT_VALUE
);
901 if (gDumpFile
== nsnull
) {
902 const nsAdoptingCString
& fname
=
903 nsContentUtils::GetCharPref("browser.dom.window.dump.file");
904 if (!fname
.IsEmpty()) {
905 // if this fails to open, Dump() knows to just go to stdout
907 gDumpFile
= fopen(fname
, "wb+");
913 if (!gEntropyCollector
) {
914 CallGetService(NS_ENTROPYCOLLECTOR_CONTRACTID
, &gEntropyCollector
);
917 mSerial
= ++gSerialCounter
;
920 printf("++DOMWINDOW == %d (%p) [serial = %d] [outer = %p]\n", gRefCnt
,
921 static_cast<void*>(static_cast<nsIScriptGlobalObject
*>(this)),
922 gSerialCounter
, static_cast<void*>(aOuterWindow
));
927 gDOMLeakPRLog
= PR_NewLogModule("DOMLeak");
930 PR_LOG(gDOMLeakPRLog
, PR_LOG_DEBUG
,
931 ("DOMWINDOW %p created outer=%p", this, aOuterWindow
));
935 nsGlobalWindow::~nsGlobalWindow()
937 if (sOuterWindowsById
) {
938 sOuterWindowsById
->Remove(mWindowID
);
941 NS_IF_RELEASE(gEntropyCollector
);
942 delete sOuterWindowsById
;
943 sOuterWindowsById
= nsnull
;
947 if (mLastOpenedURI
) {
948 mLastOpenedURI
->GetSpec(url
);
951 printf("--DOMWINDOW == %d (%p) [serial = %d] [outer = %p] [url = %s]\n",
952 gRefCnt
, static_cast<void*>(static_cast<nsIScriptGlobalObject
*>(this)),
953 mSerial
, static_cast<void*>(mOuterWindow
.get()), url
.get());
958 PR_LOG(gDOMLeakPRLog
, PR_LOG_DEBUG
,
959 ("DOMWINDOW %p destroyed", this));
962 if (IsOuterWindow()) {
963 // An outer window is destroyed with inner windows still possibly
964 // alive, iterate through the inner windows and null out their
965 // back pointer to this outer, and pull them out of the list of
969 while ((w
= (nsGlobalWindow
*)PR_LIST_HEAD(this)) != this) {
970 PR_REMOVE_AND_INIT_LINK(w
);
973 if (mListenerManager
) {
974 mListenerManager
->Disconnect();
975 mListenerManager
= nsnull
;
978 // An inner window is destroyed, pull it out of the outer window's
979 // list if inner windows.
981 PR_REMOVE_LINK(this);
983 // If our outer window's inner window is this window, null out the
984 // outer window's reference to this window that's being deleted.
985 nsGlobalWindow
*outer
= GetOuterWindowInternal();
986 if (outer
&& outer
->mInnerWindow
== this) {
987 outer
->mInnerWindow
= nsnull
;
991 mDocument
= nsnull
; // Forces Release
994 NS_ASSERTION(!mArguments
, "mArguments wasn't cleaned up properly!");
999 nsCycleCollector_DEBUG_wasFreed(static_cast<nsIScriptGlobalObject
*>(this));
1003 mURLProperty
->ClearWindowReference();
1006 nsLayoutStatics::Release();
1011 nsGlobalWindow::ShutDown()
1013 NS_IF_RELEASE(sGlobalStorageList
);
1015 if (gDumpFile
&& gDumpFile
!= stdout
) {
1023 nsGlobalWindow::CleanupCachedXBLHandlers(nsGlobalWindow
* aWindow
)
1025 if (aWindow
->mCachedXBLPrototypeHandlers
.IsInitialized() &&
1026 aWindow
->mCachedXBLPrototypeHandlers
.Count() > 0) {
1027 aWindow
->mCachedXBLPrototypeHandlers
.Clear();
1029 nsISupports
* supports
;
1030 aWindow
->QueryInterface(NS_GET_IID(nsCycleCollectionISupports
),
1031 reinterpret_cast<void**>(&supports
));
1032 NS_ASSERTION(supports
, "Failed to QI to nsCycleCollectionISupports?!");
1034 nsContentUtils::DropJSObjects(supports
);
1039 nsGlobalWindow::MaybeForgiveSpamCount()
1041 if (IsOuterWindow() &&
1042 IsPopupSpamWindow())
1044 SetPopupSpamWindow(PR_FALSE
);
1045 --gOpenPopupSpamCount
;
1046 NS_ASSERTION(gOpenPopupSpamCount
>= 0,
1047 "Unbalanced decrement of gOpenPopupSpamCount");
1052 nsGlobalWindow::CleanUp(PRBool aIgnoreModalDialog
)
1054 if (IsOuterWindow() && !aIgnoreModalDialog
) {
1055 nsGlobalWindow
* inner
= GetCurrentInnerWindowInternal();
1056 nsCOMPtr
<nsIDOMModalContentWindow
>
1057 dlg(do_QueryInterface(static_cast<nsPIDOMWindow
*>(inner
)));
1059 // The window we're trying to clean up is the outer window of a
1060 // modal dialog. Defer cleanup until the window closes, and let
1061 // ShowModalDialog take care of calling CleanUp.
1062 mCallCleanUpAfterModalDialogCloses
= PR_TRUE
;
1067 // Guarantee idempotence.
1070 mCleanedUp
= PR_TRUE
;
1073 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
1075 os
->RemoveObserver(mObserver
, NS_IOSERVICE_OFFLINE_STATUS_TOPIC
);
1076 os
->RemoveObserver(mObserver
, "dom-storage2-changed");
1077 os
->RemoveObserver(mObserver
, "dom-storage-changed");
1080 // Drop its reference to this dying window, in case for some bogus reason
1081 // the object stays around.
1082 mObserver
->Forget();
1083 NS_RELEASE(mObserver
);
1086 mNavigator
= nsnull
;
1090 mLocationbar
= nsnull
;
1091 mPersonalbar
= nsnull
;
1092 mStatusbar
= nsnull
;
1093 mScrollbars
= nsnull
;
1097 mApplicationCache
= nsnull
;
1098 mIndexedDB
= nsnull
;
1099 mPendingStorageEventsObsolete
= nsnull
;
1104 mOpener
= nsnull
; // Forces Release
1107 nsCycleCollector_DEBUG_shouldBeFreed(mContext
);
1109 mContext
= nsnull
; // Forces Release
1111 mChromeEventHandler
= nsnull
; // Forces Release
1112 mParentTarget
= nsnull
;
1114 nsGlobalWindow
*inner
= GetCurrentInnerWindowInternal();
1117 inner
->CleanUp(aIgnoreModalDialog
);
1120 DisableAccelerationUpdates();
1121 mHasAcceleration
= PR_FALSE
;
1123 if (mCleanMessageManager
) {
1124 NS_ABORT_IF_FALSE(mIsChrome
, "only chrome should have msg manager cleaned");
1125 nsGlobalChromeWindow
*asChrome
= static_cast<nsGlobalChromeWindow
*>(this);
1126 if (asChrome
->mMessageManager
) {
1127 static_cast<nsFrameMessageManager
*>(
1128 asChrome
->mMessageManager
.get())->Disconnect();
1132 mInnerWindowHolder
= nsnull
;
1133 mArguments
= nsnull
;
1134 mArgumentsLast
= nsnull
;
1135 mArgumentsOrigin
= nsnull
;
1137 CleanupCachedXBLHandlers(this);
1140 nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject
*>(this));
1145 nsGlobalWindow::ClearControllers()
1149 mControllers
->GetControllerCount(&count
);
1152 nsCOMPtr
<nsIController
> controller
;
1153 mControllers
->GetControllerAt(count
, getter_AddRefs(controller
));
1155 nsCOMPtr
<nsIControllerContext
> context
= do_QueryInterface(controller
);
1157 context
->SetCommandContext(nsnull
);
1160 mControllers
= nsnull
;
1166 nsGlobalWindow::TryClearWindowScope(nsISupports
*aWindow
)
1168 nsGlobalWindow
*window
=
1169 static_cast<nsGlobalWindow
*>(static_cast<nsIDOMWindow
*>(aWindow
));
1171 // This termination function might be called when any script evaluation in our
1172 // context terminated, even if there are other scripts in the stack. Thus, we
1173 // have to check again if a script is executing and post a new termination
1174 // function if necessary.
1175 window
->ClearScopeWhenAllScriptsStop();
1179 nsGlobalWindow::ClearScopeWhenAllScriptsStop()
1181 NS_ASSERTION(IsInnerWindow(), "Must be an inner window");
1183 // We cannot clear scope safely until all the scripts in our script context
1184 // stopped. This might be a long wait, for example if one script is busy
1185 // because it started a nested event loop for a modal dialog.
1186 nsIScriptContext
*jsscx
= GetContextInternal();
1187 if (jsscx
&& jsscx
->GetExecutingScript()) {
1188 // We ignore the return value because the only reason that we clear scope
1189 // here is to try to prevent leaks. Failing to clear scope might mean that
1190 // we'll leak more but if we don't have enough memory to allocate a
1191 // termination function we probably don't have to worry about this anyway.
1192 jsscx
->SetTerminationFunction(TryClearWindowScope
,
1193 static_cast<nsIDOMWindow
*>(this));
1197 NotifyWindowIDDestroyed("inner-window-destroyed");
1198 nsIScriptContext
*scx
= GetContextInternal();
1200 scx
->ClearScope(mJSObject
, PR_TRUE
);
1205 nsGlobalWindow::FreeInnerObjects(PRBool aClearScope
)
1207 NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
1209 // Kill all of the workers for this window.
1210 nsDOMThreadService
* dts
= nsDOMThreadService::get();
1212 nsIScriptContext
*scx
= GetContextInternal();
1214 JSContext
*cx
= scx
? (JSContext
*)scx
->GetNativeContext() : nsnull
;
1216 // Have to suspend this request here because CancelWorkersForGlobal will
1217 // lock until the worker has died and that could cause a deadlock.
1218 JSAutoSuspendRequest
asr(cx
);
1220 dts
->CancelWorkersForGlobal(static_cast<nsIScriptGlobalObject
*>(this));
1223 // Close all IndexedDB databases for this window.
1224 indexedDB::IndexedDatabaseManager
* idbManager
=
1225 indexedDB::IndexedDatabaseManager::Get();
1227 idbManager
->AbortCloseDatabasesForWindow(this);
1232 mChromeEventHandler
= nsnull
;
1234 if (mListenerManager
) {
1235 mListenerManager
->Disconnect();
1236 mListenerManager
= nsnull
;
1243 NS_ASSERTION(mDoc
, "Why is mDoc null?");
1245 // Remember the document's principal.
1246 mDocumentPrincipal
= mDoc
->NodePrincipal();
1251 nsCycleCollector_DEBUG_shouldBeFreed(nsCOMPtr
<nsISupports
>(do_QueryInterface(mDocument
)));
1254 // Make sure that this is called before we null out the document.
1255 NotifyDOMWindowDestroyed(this);
1257 // Remove our reference to the document and the document principal.
1261 if (mApplicationCache
) {
1262 static_cast<nsDOMOfflineResourceList
*>(mApplicationCache
.get())->Disconnect();
1263 mApplicationCache
= nsnull
;
1266 mIndexedDB
= nsnull
;
1269 ClearScopeWhenAllScriptsStop();
1272 if (mDummyJavaPluginOwner
) {
1273 // Tear down the dummy java plugin.
1275 // XXXjst: On a general note, should windows with java stuff in
1276 // them ever even make it into the fast-back cache?
1278 mDummyJavaPluginOwner
->Destroy();
1280 mDummyJavaPluginOwner
= nsnull
;
1283 CleanupCachedXBLHandlers(this);
1286 nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject
*>(this));
1290 //*****************************************************************************
1291 // nsGlobalWindow::nsISupports
1292 //*****************************************************************************
1294 #define OUTER_WINDOW_ONLY \
1295 if (IsOuterWindow()) {
1297 #define END_OUTER_WINDOW_ONLY \
1298 foundInterface = 0; \
1301 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindow
)
1303 DOMCI_DATA(Window
, nsGlobalWindow
)
1305 // QueryInterface implementation for nsGlobalWindow
1306 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow
)
1307 // Make sure this matches the cast in nsGlobalWindow::FromWrapper()
1308 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIScriptGlobalObject
)
1309 NS_INTERFACE_MAP_ENTRY(nsIDOMWindowInternal
)
1310 NS_INTERFACE_MAP_ENTRY(nsIDOMWindow
)
1311 NS_INTERFACE_MAP_ENTRY(nsIDOMWindow2
)
1312 NS_INTERFACE_MAP_ENTRY(nsIDOMJSWindow
)
1313 NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject
)
1314 NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal
)
1315 NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget
)
1316 NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget
)
1317 NS_INTERFACE_MAP_ENTRY(nsIDOM3EventTarget
)
1318 NS_INTERFACE_MAP_ENTRY(nsIDOMNSEventTarget
)
1319 NS_INTERFACE_MAP_ENTRY(nsPIDOMWindow
)
1320 NS_INTERFACE_MAP_ENTRY(nsIDOMViewCSS
)
1321 NS_INTERFACE_MAP_ENTRY(nsIDOMAbstractView
)
1322 NS_INTERFACE_MAP_ENTRY(nsIDOMStorageWindow
)
1323 NS_INTERFACE_MAP_ENTRY(nsIDOMStorageIndexedDB
)
1324 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
1325 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor
)
1326 NS_INTERFACE_MAP_ENTRY(nsIDOMWindow_2_0_BRANCH
)
1327 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Window
)
1329 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
1330 END_OUTER_WINDOW_ONLY
1331 NS_INTERFACE_MAP_END
1334 NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsGlobalWindow
, nsIScriptGlobalObject
)
1335 NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsGlobalWindow
,
1336 nsIScriptGlobalObject
)
1339 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGlobalWindow
)
1340 if (tmp
->mDoc
&& nsCCUncollectableMarker::InGeneration(
1341 cb
, tmp
->mDoc
->GetMarkedCCGeneration())) {
1342 return NS_SUCCESS_INTERRUPTED_TRAVERSE
;
1345 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext
)
1347 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mControllers
)
1348 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArguments
)
1349 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArgumentsLast
)
1351 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInnerWindowHolder
)
1352 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOuterWindow
)
1354 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOpenerScriptPrincipal
)
1355 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mListenerManager
)
1357 for (nsTimeout
* timeout
= tmp
->FirstTimeout();
1358 tmp
->IsTimeout(timeout
);
1359 timeout
= timeout
->Next()) {
1360 cb
.NoteNativeChild(timeout
, &NS_CYCLE_COLLECTION_NAME(nsTimeout
));
1363 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSessionStorage
)
1364 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mApplicationCache
)
1365 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocumentPrincipal
)
1366 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc
)
1368 // Traverse stuff from nsPIDOMWindow
1369 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChromeEventHandler
)
1370 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParentTarget
)
1371 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument
)
1372 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFrameElement
)
1374 // Traverse mDummyJavaPluginOwner
1375 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDummyJavaPluginOwner
)
1377 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFocusedNode
)
1379 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mPendingStorageEvents
)
1381 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
1383 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow
)
1384 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext
)
1386 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mControllers
)
1387 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mArguments
)
1388 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mArgumentsLast
)
1390 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInnerWindowHolder
)
1391 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOuterWindow
)
1393 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOpenerScriptPrincipal
)
1394 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListenerManager
)
1395 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSessionStorage
)
1396 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mApplicationCache
)
1397 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocumentPrincipal
)
1399 // Unlink stuff from nsPIDOMWindow
1400 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChromeEventHandler
)
1401 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParentTarget
)
1402 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument
)
1403 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFrameElement
)
1405 // Unlink mDummyJavaPluginOwner
1406 if (tmp
->mDummyJavaPluginOwner
) {
1407 tmp
->mDummyJavaPluginOwner
->Destroy();
1408 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDummyJavaPluginOwner
)
1411 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFocusedNode
)
1413 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mPendingStorageEvents
)
1415 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
1419 TraceData(TraceCallback
& aCallback
, void* aClosure
) :
1420 callback(aCallback
), closure(aClosure
) {}
1422 TraceCallback
& callback
;
1426 static PLDHashOperator
1427 TraceXBLHandlers(const void* aKey
, void* aData
, void* aClosure
)
1429 TraceData
* data
= static_cast<TraceData
*>(aClosure
);
1430 data
->callback(nsIProgrammingLanguage::JAVASCRIPT
, aData
, data
->closure
);
1431 return PL_DHASH_NEXT
;
1434 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindow
)
1435 if (tmp
->mCachedXBLPrototypeHandlers
.IsInitialized()) {
1436 TraceData
data(aCallback
, aClosure
);
1437 tmp
->mCachedXBLPrototypeHandlers
.EnumerateRead(TraceXBLHandlers
, &data
);
1439 NS_IMPL_CYCLE_COLLECTION_TRACE_END
1441 NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsGlobalWindow
)
1442 nsGlobalWindow::CleanupCachedXBLHandlers(tmp
);
1443 NS_IMPL_CYCLE_COLLECTION_ROOT_END
1445 //*****************************************************************************
1446 // nsGlobalWindow::nsIScriptGlobalObject
1447 //*****************************************************************************
1450 nsGlobalWindow::SetScriptContext(PRUint32 lang_id
, nsIScriptContext
*aScriptContext
)
1452 NS_ASSERTION(lang_id
== nsIProgrammingLanguage::JAVASCRIPT
,
1453 "We don't support this language ID");
1454 NS_ASSERTION(IsOuterWindow(), "Uh, SetScriptContext() called on inner window!");
1456 NS_ASSERTION(!aScriptContext
|| !mContext
, "Bad call to SetContext()!");
1458 if (aScriptContext
) {
1459 // should probably assert the context is clean???
1460 aScriptContext
->WillInitializeContext();
1462 nsresult rv
= aScriptContext
->InitContext();
1463 NS_ENSURE_SUCCESS(rv
, rv
);
1466 // This window is a [i]frame, don't bother GC'ing when the
1467 // frame's context is destroyed since a GC will happen when the
1468 // frameset or host document is destroyed anyway.
1470 aScriptContext
->SetGCOnDestruction(PR_FALSE
);
1474 mContext
= aScriptContext
;
1479 nsGlobalWindow::EnsureScriptEnvironment(PRUint32 aLangID
)
1481 NS_ASSERTION(aLangID
== nsIProgrammingLanguage::JAVASCRIPT
,
1482 "We don't support this language ID");
1483 FORWARD_TO_OUTER(EnsureScriptEnvironment
, (aLangID
), NS_ERROR_NOT_INITIALIZED
);
1488 NS_ASSERTION(!GetCurrentInnerWindowInternal(),
1489 "mJSObject is null, but we have an inner window?");
1491 nsCOMPtr
<nsIScriptRuntime
> scriptRuntime
;
1492 nsresult rv
= NS_GetScriptRuntimeByID(aLangID
, getter_AddRefs(scriptRuntime
));
1493 NS_ENSURE_SUCCESS(rv
, rv
);
1495 nsCOMPtr
<nsIScriptContext
> context
;
1496 rv
= scriptRuntime
->CreateContext(getter_AddRefs(context
));
1497 NS_ENSURE_SUCCESS(rv
, rv
);
1499 return SetScriptContext(aLangID
, context
);
1503 nsGlobalWindow::GetScriptContext(PRUint32 lang
)
1505 NS_ASSERTION(lang
== nsIProgrammingLanguage::JAVASCRIPT
,
1506 "We don't support this language ID");
1508 FORWARD_TO_OUTER(GetScriptContext
, (lang
), nsnull
);
1513 nsGlobalWindow::GetScriptGlobal(PRUint32 lang
)
1515 NS_ASSERTION(lang
== nsIProgrammingLanguage::JAVASCRIPT
,
1516 "We don't support this language ID");
1521 nsGlobalWindow::GetContext()
1523 FORWARD_TO_OUTER(GetContext
, (), nsnull
);
1525 // check GetContext is indeed identical to GetScriptContext()
1526 NS_ASSERTION(mContext
== GetScriptContext(nsIProgrammingLanguage::JAVASCRIPT
),
1527 "GetContext confused?");
1532 nsGlobalWindow::GetGlobalJSObject()
1534 NS_ASSERTION(mJSObject
== GetScriptGlobal(nsIProgrammingLanguage::JAVASCRIPT
),
1535 "GetGlobalJSObject confused?");
1536 return FastGetGlobalJSObject();
1540 nsGlobalWindow::WouldReuseInnerWindow(nsIDocument
*aNewDocument
)
1542 // We reuse the inner window when:
1543 // a. We are currently at our original document.
1544 // b. At least one of the following conditions are true:
1545 // -- We are not currently a content window (i.e., we're currently a chrome
1547 // -- The new document is the same as the old document. This means that we're
1548 // getting called from document.open().
1549 // -- The new document has the same origin as what we have loaded right now.
1551 if (!mDoc
|| !aNewDocument
) {
1555 if (!mDoc
->IsInitialDocument()) {
1559 NS_ASSERTION(IsAboutBlank(mDoc
->GetDocumentURI()),
1560 "How'd this happen?");
1562 // Great, we're the original document, check for one of the other
1564 if (mDoc
== aNewDocument
) {
1565 // aClearScopeHint is false.
1570 if (NS_SUCCEEDED(mDoc
->NodePrincipal()->Equals(aNewDocument
->NodePrincipal(),
1573 // The origin is the same.
1577 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(do_QueryInterface(mDocShell
));
1580 PRInt32 itemType
= nsIDocShellTreeItem::typeContent
;
1581 treeItem
->GetItemType(&itemType
);
1583 // If we're a chrome window, then we want to reuse the inner window.
1584 return itemType
== nsIDocShellTreeItem::typeChrome
;
1587 // No treeItem: don't reuse the current inner window.
1592 nsGlobalWindow::SetOpenerScriptPrincipal(nsIPrincipal
* aPrincipal
)
1594 FORWARD_TO_OUTER_VOID(SetOpenerScriptPrincipal
, (aPrincipal
));
1597 if (!mDoc
->IsInitialDocument()) {
1598 // We have a document already, and it's not the original one. Bail out.
1599 // Do NOT set mOpenerScriptPrincipal in this case, just to be safe.
1604 // We better have an about:blank document loaded at this point. Otherwise,
1605 // something is really weird.
1606 nsCOMPtr
<nsIURI
> uri
;
1607 mDoc
->NodePrincipal()->GetURI(getter_AddRefs(uri
));
1608 NS_ASSERTION(uri
&& IsAboutBlank(uri
) &&
1609 IsAboutBlank(mDoc
->GetDocumentURI()),
1610 "Unexpected original document");
1613 nsCOMPtr
<nsIDocShell_MOZILLA_2_0_BRANCH
> ds(do_QueryInterface(GetDocShell()));
1614 ds
->CreateAboutBlankContentViewer(aPrincipal
);
1615 mDoc
->SetIsInitialDocument(PR_TRUE
);
1620 nsGlobalWindow::GetOpenerScriptPrincipal()
1622 FORWARD_TO_OUTER(GetOpenerScriptPrincipal
, (), nsnull
);
1624 return mOpenerScriptPrincipal
;
1628 PushPopupControlState(PopupControlState aState
, PRBool aForce
)
1630 PopupControlState oldState
= gPopupControlState
;
1632 if (aState
< gPopupControlState
|| aForce
) {
1633 gPopupControlState
= aState
;
1640 PopPopupControlState(PopupControlState aState
)
1642 gPopupControlState
= aState
;
1646 nsGlobalWindow::PushPopupControlState(PopupControlState aState
,
1647 PRBool aForce
) const
1649 return ::PushPopupControlState(aState
, aForce
);
1653 nsGlobalWindow::PopPopupControlState(PopupControlState aState
) const
1655 ::PopPopupControlState(aState
);
1659 nsGlobalWindow::GetPopupControlState() const
1661 return gPopupControlState
;
1664 #define WINDOWSTATEHOLDER_IID \
1665 {0x0b917c3e, 0xbd50, 0x4683, {0xaf, 0xc9, 0xc7, 0x81, 0x07, 0xae, 0x33, 0x26}}
1667 class WindowStateHolder
: public nsISupports
1670 NS_DECLARE_STATIC_IID_ACCESSOR(WINDOWSTATEHOLDER_IID
)
1673 WindowStateHolder(nsGlobalWindow
*aWindow
,
1674 nsIXPConnectJSObjectHolder
*aHolder
,
1675 nsNavigator
*aNavigator
,
1676 nsIXPConnectJSObjectHolder
*aOuterProto
,
1677 nsIXPConnectJSObjectHolder
*aOuterRealProto
);
1679 nsGlobalWindow
* GetInnerWindow() { return mInnerWindow
; }
1680 nsIXPConnectJSObjectHolder
*GetInnerWindowHolder()
1681 { return mInnerWindowHolder
; }
1683 nsNavigator
* GetNavigator() { return mNavigator
; }
1684 nsIXPConnectJSObjectHolder
* GetOuterProto() { return mOuterProto
; }
1685 nsIXPConnectJSObjectHolder
* GetOuterRealProto() { return mOuterRealProto
; }
1687 void DidRestoreWindow()
1689 mInnerWindow
= nsnull
;
1691 mInnerWindowHolder
= nsnull
;
1692 mNavigator
= nsnull
;
1693 mOuterProto
= nsnull
;
1694 mOuterRealProto
= nsnull
;
1698 ~WindowStateHolder();
1700 nsGlobalWindow
*mInnerWindow
;
1701 // We hold onto this to make sure the inner window doesn't go away. The outer
1702 // window ends up recalculating it anyway.
1703 nsCOMPtr
<nsIXPConnectJSObjectHolder
> mInnerWindowHolder
;
1704 nsRefPtr
<nsNavigator
> mNavigator
;
1705 nsCOMPtr
<nsIXPConnectJSObjectHolder
> mOuterProto
;
1706 nsCOMPtr
<nsIXPConnectJSObjectHolder
> mOuterRealProto
;
1709 NS_DEFINE_STATIC_IID_ACCESSOR(WindowStateHolder
, WINDOWSTATEHOLDER_IID
)
1711 WindowStateHolder::WindowStateHolder(nsGlobalWindow
*aWindow
,
1712 nsIXPConnectJSObjectHolder
*aHolder
,
1713 nsNavigator
*aNavigator
,
1714 nsIXPConnectJSObjectHolder
*aOuterProto
,
1715 nsIXPConnectJSObjectHolder
*aOuterRealProto
)
1716 : mInnerWindow(aWindow
),
1717 mNavigator(aNavigator
),
1718 mOuterProto(aOuterProto
),
1719 mOuterRealProto(aOuterRealProto
)
1721 NS_PRECONDITION(aWindow
, "null window");
1722 NS_PRECONDITION(aWindow
->IsInnerWindow(), "Saving an outer window");
1724 mInnerWindowHolder
= aHolder
;
1726 aWindow
->SuspendTimeouts();
1729 WindowStateHolder::~WindowStateHolder()
1732 // This window was left in the bfcache and is now going away. We need to
1734 // Note that FreeInnerObjects may already have been called on the
1735 // inner window if its outer has already had SetDocShell(null)
1736 // called. In this case the contexts will all be null and the
1737 // PR_TRUE for aClearScope won't do anything; this is OK since
1738 // SetDocShell(null) already did it.
1739 mInnerWindow
->FreeInnerObjects(PR_TRUE
);
1743 NS_IMPL_ISUPPORTS1(WindowStateHolder
, WindowStateHolder
)
1746 nsGlobalWindow::SetNewDocument(nsIDocument
* aDocument
,
1747 nsISupports
* aState
,
1748 PRBool aForceReuseInnerWindow
)
1752 NS_PRECONDITION(mDocumentPrincipal
== nsnull
,
1753 "mDocumentPrincipal prematurely set!");
1756 NS_ERROR("SetNewDocument(null) called!");
1758 return NS_ERROR_INVALID_ARG
;
1761 if (IsInnerWindow()) {
1762 if (!mOuterWindow
) {
1763 return NS_ERROR_NOT_INITIALIZED
;
1766 // Refuse to set a new document if the call came from an inner
1767 // window that's not the current inner window.
1768 if (mOuterWindow
->GetCurrentInnerWindow() != this) {
1769 return NS_ERROR_NOT_AVAILABLE
;
1772 return GetOuterWindowInternal()->SetNewDocument(aDocument
, aState
,
1773 aForceReuseInnerWindow
);
1776 NS_PRECONDITION(IsOuterWindow(), "Must only be called on outer windows");
1779 // This outer is now getting its first inner, thaw the outer now
1780 // that it's ready and is getting an inner window.
1785 NS_ASSERTION(!GetCurrentInnerWindow() ||
1786 GetCurrentInnerWindow()->GetExtantDocument() == mDocument
,
1787 "Uh, mDocument doesn't match the current inner window "
1790 PRBool wouldReuseInnerWindow
= WouldReuseInnerWindow(aDocument
);
1791 if (aForceReuseInnerWindow
&&
1792 !wouldReuseInnerWindow
&&
1794 mDoc
->NodePrincipal() != aDocument
->NodePrincipal()) {
1795 NS_ERROR("Attempted forced inner window reuse while changing principal");
1796 return NS_ERROR_UNEXPECTED
;
1799 nsresult rv
= NS_OK
;
1801 nsCOMPtr
<nsIDocument
> oldDoc(do_QueryInterface(mDocument
));
1803 nsIScriptContext
*scx
= GetContextInternal();
1804 NS_ENSURE_TRUE(scx
, NS_ERROR_NOT_INITIALIZED
);
1806 JSContext
*cx
= (JSContext
*)scx
->GetNativeContext();
1807 #ifndef MOZ_DISABLE_DOMCRYPTO
1808 // clear smartcard events, our document has gone away.
1810 mCrypto
->SetEnableSmartCardEvents(PR_FALSE
);
1814 // First document load.
1816 // Get our private root. If it is equal to us, then we need to
1817 // attach our global key bindings that handles browser scrolling
1818 // and other browser commands.
1819 nsIDOMWindowInternal
*internal
= nsGlobalWindow::GetPrivateRoot();
1821 if (internal
== static_cast<nsIDOMWindowInternal
*>(this)) {
1822 nsCOMPtr
<nsIXBLService
> xblService
= do_GetService("@mozilla.org/xbl;1");
1824 nsCOMPtr
<nsPIDOMEventTarget
> piTarget
=
1825 do_QueryInterface(mChromeEventHandler
);
1826 xblService
->AttachGlobalKeyHandler(piTarget
);
1831 /* No mDocShell means we're already been partially closed down. When that
1832 happens, setting status isn't a big requirement, so don't. (Doesn't happen
1833 under normal circumstances, but bug 49615 describes a case.) */
1835 nsContentUtils::AddScriptRunner(
1836 NS_NewRunnableMethod(this, &nsGlobalWindow::ClearStatus
));
1838 PRBool reUseInnerWindow
= aForceReuseInnerWindow
|| wouldReuseInnerWindow
;
1840 // Remember the old document's principal.
1841 nsIPrincipal
*oldPrincipal
= nsnull
;
1843 oldPrincipal
= oldDoc
->NodePrincipal();
1846 // Drop our reference to the navigator object unless we're reusing
1847 // the existing inner window or the new document is from the same
1848 // origin as the old document.
1849 if (!reUseInnerWindow
&& mNavigator
&& oldPrincipal
) {
1851 rv
= oldPrincipal
->Equals(aDocument
->NodePrincipal(), &equal
);
1853 if (NS_FAILED(rv
) || !equal
) {
1854 // Different origins. Release the navigator object so it gets
1855 // recreated for the new document. The plugins or mime types
1856 // arrays may have changed. See bug 150087.
1857 mNavigator
->SetDocShell(nsnull
);
1859 mNavigator
= nsnull
;
1863 if (mNavigator
&& aDocument
!= oldDoc
) {
1864 // We didn't drop our reference to our old navigator object and
1865 // we're loading a new document. Notify the navigator object about
1866 // the new document load so that it can make sure it is ready for
1867 // the new document.
1869 mNavigator
->LoadingNewDocument();
1872 // Set mDocument even if this is an outer window to avoid
1873 // having to *always* reach into the inner window to find the
1875 mDocument
= do_QueryInterface(aDocument
);
1879 mLastOpenedURI
= aDocument
->GetDocumentURI();
1882 mContext
->WillInitializeContext();
1884 nsGlobalWindow
*currentInner
= GetCurrentInnerWindowInternal();
1886 nsRefPtr
<nsGlobalWindow
> newInnerWindow
;
1888 PRBool thisChrome
= IsChromeWindow();
1889 nsCOMPtr
<nsIXPConnectJSObjectHolder
> navigatorHolder
;
1892 PRBool isChrome
= PR_FALSE
;
1894 nsCxPusher cxPusher
;
1895 if (!cxPusher
.Push(cx
)) {
1896 return NS_ERROR_FAILURE
;
1899 JSAutoRequest
ar(cx
);
1901 nsCOMPtr
<WindowStateHolder
> wsh
= do_QueryInterface(aState
);
1902 NS_ASSERTION(!aState
|| wsh
, "What kind of weird state are you giving me here?");
1904 // Make sure to clear scope on the outer window *before* we
1905 // initialize the new inner window. If we don't, things
1906 // (Object.prototype etc) could leak from the old outer to the new
1908 mContext
->ClearScope(mJSObject
, PR_FALSE
);
1910 // This code should not be called during shutdown any more (now that
1911 // we don't ever call SetNewDocument(nsnull), so no need to null
1913 nsIXPConnect
*xpc
= nsContentUtils::XPConnect();
1914 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
1915 if (reUseInnerWindow
) {
1916 // We're reusing the current inner window.
1917 NS_ASSERTION(!currentInner
->IsFrozen(),
1918 "We should never be reusing a shared inner window");
1919 newInnerWindow
= currentInner
;
1921 if (aDocument
!= oldDoc
) {
1922 nsWindowSH::InvalidateGlobalScopePolluter(cx
, currentInner
->mJSObject
);
1925 // The API we're really looking for here is to go clear all of the
1926 // Xray wrappers associated with our outer window. However, we
1927 // don't expose that API because the implementation would be
1928 // identical to that of JS_TransplantObject, so we just call that
1930 if (!JS_TransplantObject(cx
, mJSObject
, mJSObject
)) {
1931 return NS_ERROR_FAILURE
;
1935 newInnerWindow
= wsh
->GetInnerWindow();
1936 mInnerWindowHolder
= wsh
->GetInnerWindowHolder();
1938 NS_ASSERTION(newInnerWindow
, "Got a state without inner window");
1940 // These assignments addref.
1941 mNavigator
= wsh
->GetNavigator();
1944 // Update mNavigator's docshell pointer now.
1945 mNavigator
->SetDocShell(mDocShell
);
1946 mNavigator
->LoadingNewDocument();
1948 } else if (thisChrome
) {
1949 newInnerWindow
= new nsGlobalChromeWindow(this);
1951 } else if (mIsModalContentWindow
) {
1952 newInnerWindow
= new nsGlobalModalWindow(this);
1954 newInnerWindow
= new nsGlobalWindow(this);
1957 if (currentInner
&& currentInner
->mJSObject
) {
1958 if (mNavigator
&& !aState
) {
1959 // Hold on to the navigator wrapper so that we can set
1960 // window.navigator in the new window to point to the same
1961 // object (assuming we didn't change origins etc). See bug
1962 // 163645 for more on why we need this.
1964 nsIDOMNavigator
* navigator
=
1965 static_cast<nsIDOMNavigator
*>(mNavigator
.get());
1966 nsContentUtils::WrapNative(cx
, currentInner
->mJSObject
, navigator
,
1967 &NS_GET_IID(nsIDOMNavigator
), &nav
,
1968 getter_AddRefs(navigatorHolder
));
1973 // This is redundant if we're restoring from a previous inner window.
1974 nsIScriptGlobalObject
*sgo
=
1975 (nsIScriptGlobalObject
*)newInnerWindow
.get();
1977 // Freeze the outer window and null out the inner window so
1978 // that initializing classes on the new inner doesn't end up
1979 // reaching into the old inner window for classes etc.
1981 // [This happens with Object.prototype when XPConnect creates
1982 // a temporary global while initializing classes; the reason
1983 // being that xpconnect creates the temp global w/o a parent
1984 // and proto, which makes the JS engine look up classes in
1985 // cx->globalObject, i.e. this outer window].
1987 mInnerWindow
= nsnull
;
1990 mCreatingInnerWindow
= PR_TRUE
;
1991 // Every script context we are initialized with must create a
1993 void *&newGlobal
= (void *&)newInnerWindow
->mJSObject
;
1994 nsCOMPtr
<nsIXPConnectJSObjectHolder
> &holder
= mInnerWindowHolder
;
1995 rv
= mContext
->CreateNativeGlobalForInner(sgo
, isChrome
,
1996 aDocument
->NodePrincipal(),
1998 getter_AddRefs(holder
));
1999 NS_ASSERTION(NS_SUCCEEDED(rv
) && newGlobal
&& holder
,
2000 "Failed to get script global and holder");
2002 mCreatingInnerWindow
= PR_FALSE
;
2005 NS_ENSURE_SUCCESS(rv
, rv
);
2008 if (currentInner
&& currentInner
->mJSObject
) {
2009 PRBool termFuncSet
= PR_FALSE
;
2011 if (oldDoc
== aDocument
) {
2012 // Suspend the current context's request before Pop() resumes the old
2013 // context's request.
2014 JSAutoSuspendRequest
asr(cx
);
2016 // Pop our context here so that we get the correct one for the
2017 // termination function.
2020 JSContext
*oldCx
= nsContentUtils::GetCurrentJSContext();
2022 nsIScriptContext
*callerScx
;
2023 if (oldCx
&& (callerScx
= GetScriptContextFromJSContext(oldCx
))) {
2024 // We're called from document.open() (and document.open() is
2025 // called from JS), clear the scope etc in a termination
2026 // function on the calling context to prevent clearing the
2028 NS_ASSERTION(!currentInner
->IsFrozen(),
2029 "How does this opened window get into session history");
2031 JSAutoRequest
ar(oldCx
);
2033 callerScx
->SetTerminationFunction(ClearWindowScope
,
2034 static_cast<nsIDOMWindow
*>
2037 termFuncSet
= PR_TRUE
;
2040 // Re-push our context.
2044 // Don't clear scope on our current inner window if it's going to be
2045 // held in the bfcache.
2046 if (!currentInner
->IsFrozen()) {
2047 // Skip the ClearScope if we set a termination function to do
2048 // it ourselves, later.
2049 currentInner
->FreeInnerObjects(!termFuncSet
);
2053 mInnerWindow
= newInnerWindow
;
2056 mContext
->CreateOuterObject(this, newInnerWindow
);
2057 mContext
->DidInitializeContext();
2059 mJSObject
= (JSObject
*)mContext
->GetNativeGlobal();
2060 SetWrapper(mJSObject
);
2062 JSObject
*outerObject
=
2063 NS_NewOuterWindowProxy(cx
, newInnerWindow
->mJSObject
);
2065 NS_ERROR("out of memory");
2066 return NS_ERROR_FAILURE
;
2069 outerObject
= JS_TransplantObject(cx
, mJSObject
, outerObject
);
2071 NS_ERROR("unable to transplant wrappers, probably OOM");
2072 return NS_ERROR_FAILURE
;
2075 mJSObject
= outerObject
;
2076 SetWrapper(mJSObject
);
2079 JSAutoEnterCompartment ac
;
2080 if (!ac
.enter(cx
, mJSObject
)) {
2081 NS_ERROR("unable to enter a compartment");
2082 return NS_ERROR_FAILURE
;
2085 JS_SetParent(cx
, mJSObject
, newInnerWindow
->mJSObject
);
2087 mContext
->SetOuterObject(mJSObject
);
2091 JSAutoEnterCompartment ac
;
2092 if (!ac
.enter(cx
, mJSObject
)) {
2093 NS_ERROR("unable to enter a compartment");
2094 return NS_ERROR_FAILURE
;
2097 // XXX Not sure if this is needed.
2100 if (nsIXPConnectJSObjectHolder
*holder
= wsh
->GetOuterRealProto()) {
2101 holder
->GetJSObject(&proto
);
2106 if (!JS_SetPrototype(cx
, mJSObject
, proto
)) {
2107 NS_ERROR("can't set prototype");
2108 return NS_ERROR_FAILURE
;
2111 if (!JS_DefineProperty(cx
, newInnerWindow
->mJSObject
, "window",
2112 OBJECT_TO_JSVAL(mJSObject
),
2113 JS_PropertyStub
, JS_StrictPropertyStub
,
2114 JSPROP_ENUMERATE
| JSPROP_READONLY
| JSPROP_PERMANENT
)) {
2115 NS_ERROR("can't create the 'window' property");
2116 return NS_ERROR_FAILURE
;
2121 JSAutoEnterCompartment ac
;
2122 if (!ac
.enter(cx
, mJSObject
)) {
2123 NS_ERROR("unable to enter a compartment");
2124 return NS_ERROR_FAILURE
;
2127 if (!aState
&& !reUseInnerWindow
) {
2128 // Loading a new page and creating a new inner window, *not*
2129 // restoring from session history.
2131 // Now that both the the inner and outer windows are initialized
2132 // let the script context do its magic to hook them together.
2133 mContext
->ConnectToInner(newInnerWindow
, mJSObject
);
2135 nsCOMPtr
<nsIContent
> frame
= do_QueryInterface(GetFrameElementInternal());
2136 if (frame
&& frame
->GetOwnerDoc()) {
2137 nsPIDOMWindow
* parentWindow
= frame
->GetOwnerDoc()->GetWindow();
2138 if (parentWindow
&& parentWindow
->TimeoutSuspendCount()) {
2139 SuspendTimeouts(parentWindow
->TimeoutSuspendCount());
2144 // Tell the contexts we have completed setting up the doc.
2145 // Add an extra ref in case we release mContext during GC.
2146 nsCOMPtr
<nsIScriptContext
> kungFuDeathGrip(mContext
);
2147 nsCOMPtr
<nsIDOMDocument
> dd(do_QueryInterface(aDocument
));
2148 mContext
->DidSetDocument(dd
, newInnerWindow
->mJSObject
);
2150 // Now that the prototype is all set up, install the global scope
2151 // polluter. This must happen after the above prototype fixup. If
2152 // the GSP was to be installed on the inner window's real
2153 // prototype (as it would be if this was done before the prototype
2154 // fixup above) we would end up holding the GSP alive (through
2155 // XPConnect's internal marking of wrapper prototypes) as long as
2156 // the inner window was around, and if the GSP had properties on
2157 // it that held an element alive we'd hold the document alive,
2158 // which could hold event handlers alive, which hold the context
2161 if ((!reUseInnerWindow
|| aDocument
!= oldDoc
) && !aState
) {
2162 nsCOMPtr
<nsIHTMLDocument
> html_doc(do_QueryInterface(mDocument
));
2163 nsWindowSH::InstallGlobalScopePolluter(cx
, newInnerWindow
->mJSObject
,
2168 aDocument
->SetScriptGlobalObject(newInnerWindow
);
2172 if (reUseInnerWindow
) {
2173 if (newInnerWindow
->mDoc
!= aDocument
) {
2174 newInnerWindow
->mDocument
= do_QueryInterface(aDocument
);
2175 newInnerWindow
->mDoc
= aDocument
;
2177 // We're reusing the inner window for a new document. In this
2178 // case we don't clear the inner window's scope, but we must
2179 // make sure the cached document property gets updated.
2181 // XXXmarkh - tell other languages about this?
2182 ::JS_DeleteProperty(cx
, currentInner
->mJSObject
, "document");
2185 rv
= newInnerWindow
->InnerSetNewDocument(aDocument
);
2186 NS_ENSURE_SUCCESS(rv
, rv
);
2188 // Initialize DOM classes etc on the inner window.
2189 rv
= mContext
->InitClasses(newInnerWindow
->mJSObject
);
2190 NS_ENSURE_SUCCESS(rv
, rv
);
2192 if (navigatorHolder
) {
2193 JS_ASSERT(JSVAL_IS_OBJECT(nav
));
2195 if (JSVAL_TO_OBJECT(nav
)->compartment() == newInnerWindow
->mJSObject
->compartment()) {
2196 // Restore window.navigator onto the new inner window.
2198 ::JS_DefineProperty(cx
, newInnerWindow
->mJSObject
, "navigator",
2199 nav
, nsnull
, nsnull
,
2200 JSPROP_ENUMERATE
| JSPROP_PERMANENT
|
2203 // The Navigator's prototype object keeps a reference to the
2204 // window in which it was first created and can thus cause that
2205 // window to stay alive for too long. Reparenting it here allows
2206 // the window to be collected sooner.
2207 nsIDOMNavigator
* navigator
=
2208 static_cast<nsIDOMNavigator
*>(mNavigator
);
2211 ReparentWrappedNativeIfFound(cx
, JSVAL_TO_OBJECT(nav
),
2212 newInnerWindow
->mJSObject
,
2214 getter_AddRefs(navigatorHolder
));
2220 newInnerWindow
->DefineArgumentsProperty(mArguments
);
2221 newInnerWindow
->mArguments
= mArguments
;
2222 newInnerWindow
->mArgumentsOrigin
= mArgumentsOrigin
;
2224 mArguments
= nsnull
;
2225 mArgumentsOrigin
= nsnull
;
2228 // Give the new inner window our chrome event handler (since it
2229 // doesn't have one).
2230 newInnerWindow
->mChromeEventHandler
= mChromeEventHandler
;
2234 mContext
->DidInitializeContext();
2236 if (newInnerWindow
&& !newInnerWindow
->mHasNotifiedGlobalCreated
&& mDoc
) {
2237 // We should probably notify. However if this is the, arguably bad,
2238 // situation when we're creating a temporary non-chrome-about-blank
2239 // document in a chrome docshell, don't notify just yet. Instead wait
2240 // until we have a real chrome doc.
2241 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(do_QueryInterface(mDocShell
));
2242 PRInt32 itemType
= nsIDocShellTreeItem::typeContent
;
2244 treeItem
->GetItemType(&itemType
);
2247 if (itemType
!= nsIDocShellTreeItem::typeChrome
||
2248 nsContentUtils::IsSystemPrincipal(mDoc
->NodePrincipal())) {
2249 newInnerWindow
->mHasNotifiedGlobalCreated
= PR_TRUE
;
2250 nsContentUtils::AddScriptRunner(
2251 NS_NewRunnableMethod(this, &nsGlobalWindow::DispatchDOMWindowCreated
));
2259 nsGlobalWindow::DispatchDOMWindowCreated()
2261 if (!mDoc
|| !mDocument
) {
2265 // Fire DOMWindowCreated at chrome event listeners
2266 nsContentUtils::DispatchChromeEvent(mDoc
, mDocument
, NS_LITERAL_STRING("DOMWindowCreated"),
2267 PR_TRUE
/* bubbles */,
2268 PR_FALSE
/* not cancellable */);
2270 nsCOMPtr
<nsIObserverService
> observerService
=
2271 mozilla::services::GetObserverService();
2272 if (observerService
) {
2273 nsAutoString origin
;
2274 nsIPrincipal
* principal
= mDoc
->NodePrincipal();
2275 nsContentUtils::GetUTFOrigin(principal
, origin
);
2277 NotifyObservers(static_cast<nsIDOMWindow
*>(this),
2278 nsContentUtils::IsSystemPrincipal(principal
) ?
2279 "chrome-document-global-created" :
2280 "content-document-global-created",
2286 nsGlobalWindow::ClearStatus()
2288 SetStatus(EmptyString());
2289 SetDefaultStatus(EmptyString());
2293 nsGlobalWindow::InnerSetNewDocument(nsIDocument
* aDocument
)
2295 NS_PRECONDITION(IsInnerWindow(), "Must only be called on inner windows");
2298 if (aDocument
&& gDOMLeakPRLog
&&
2299 PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
2300 nsIURI
*uri
= aDocument
->GetDocumentURI();
2304 PR_LogPrint("DOMWINDOW %p SetNewDocument %s", this, spec
.get());
2308 mDocument
= do_QueryInterface(aDocument
);
2310 mLocalStorage
= nsnull
;
2311 mSessionStorage
= nsnull
;
2314 mLastOpenedURI
= aDocument
->GetDocumentURI();
2317 // Clear our mutation bitfield.
2324 nsGlobalWindow::SetDocShell(nsIDocShell
* aDocShell
)
2326 NS_ASSERTION(IsOuterWindow(), "Uh, SetDocShell() called on inner window!");
2328 if (aDocShell
== mDocShell
)
2331 // SetDocShell(nsnull) means the window is being torn down. Drop our
2332 // reference to the script context, allowing it to be deleted
2333 // later. Meanwhile, keep our weak reference to the script object
2334 // (mJSObject) so that it can be retrieved later (until it is
2335 // finalized by the JS GC).
2338 NS_ASSERTION(PR_CLIST_IS_EMPTY(&mTimeouts
),
2339 "Uh, outer window holds timeouts!");
2341 // Call FreeInnerObjects on all inner windows, not just the current
2342 // one, since some could be held by WindowStateHolder objects that
2344 for (nsRefPtr
<nsGlobalWindow
> inner
= (nsGlobalWindow
*)PR_LIST_HEAD(this);
2346 inner
= (nsGlobalWindow
*)PR_NEXT_LINK(inner
)) {
2347 NS_ASSERTION(!inner
->mOuterWindow
|| inner
->mOuterWindow
== this,
2348 "bad outer window pointer");
2349 inner
->FreeInnerObjects(PR_TRUE
);
2352 // Make sure that this is called before we null out the document.
2353 NotifyDOMWindowDestroyed(this);
2355 NotifyWindowIDDestroyed("outer-window-destroyed");
2357 nsGlobalWindow
*currentInner
= GetCurrentInnerWindowInternal();
2360 NS_ASSERTION(mDoc
, "Must have doc!");
2362 // Remember the document's principal.
2363 mDocumentPrincipal
= mDoc
->NodePrincipal();
2365 // Release our document reference
2371 mContext
->ClearScope(mJSObject
, PR_TRUE
);
2376 mChromeEventHandler
= nsnull
; // force release now
2379 // We got no new document after someone called
2380 // SetArguments(), drop our reference to the arguments.
2381 mArguments
= nsnull
;
2382 mArgumentsLast
= nsnull
;
2383 mArgumentsOrigin
= nsnull
;
2388 mContext
->FinalizeContext();
2393 nsCycleCollector_DEBUG_shouldBeFreed(mContext
);
2394 nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject
*>(this));
2398 mDocShell
= aDocShell
; // Weak Reference
2401 mNavigator
->SetDocShell(aDocShell
);
2403 mFrames
->SetDocShell(aDocShell
);
2405 mScreen
->SetDocShell(aDocShell
);
2407 // tell our member elements about the new browserwindow
2408 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2409 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2411 mMenubar
->SetWebBrowserChrome(browserChrome
);
2414 mToolbar
->SetWebBrowserChrome(browserChrome
);
2417 mLocationbar
->SetWebBrowserChrome(browserChrome
);
2420 mPersonalbar
->SetWebBrowserChrome(browserChrome
);
2423 mStatusbar
->SetWebBrowserChrome(browserChrome
);
2426 mScrollbars
->SetWebBrowserChrome(browserChrome
);
2430 MaybeForgiveSpamCount();
2433 // Get our enclosing chrome shell and retrieve its global window impl, so
2434 // that we can do some forwarding to the chrome document.
2435 nsCOMPtr
<nsIDOMEventTarget
> chromeEventHandler
;
2436 mDocShell
->GetChromeEventHandler(getter_AddRefs(chromeEventHandler
));
2437 mChromeEventHandler
= do_QueryInterface(chromeEventHandler
);
2438 if (!mChromeEventHandler
) {
2439 // We have no chrome event handler. If we have a parent,
2440 // get our chrome event handler from the parent. If
2441 // we don't have a parent, then we need to make a new
2442 // window root object that will function as a chrome event
2443 // handler and receive all events that occur anywhere inside
2445 nsCOMPtr
<nsIDOMWindow
> parentWindow
;
2446 GetParent(getter_AddRefs(parentWindow
));
2447 if (parentWindow
.get() != static_cast<nsIDOMWindow
*>(this)) {
2448 nsCOMPtr
<nsPIDOMWindow
> piWindow(do_QueryInterface(parentWindow
));
2449 mChromeEventHandler
= piWindow
->GetChromeEventHandler();
2451 else NS_NewWindowRoot(this, getter_AddRefs(mChromeEventHandler
));
2457 nsGlobalWindow::SetOpenerWindow(nsIDOMWindowInternal
* aOpener
,
2458 PRBool aOriginalOpener
)
2460 FORWARD_TO_OUTER_VOID(SetOpenerWindow
, (aOpener
, aOriginalOpener
));
2462 NS_ASSERTION(!aOriginalOpener
|| !mSetOpenerWindowCalled
,
2463 "aOriginalOpener is true, but not first call to "
2464 "SetOpenerWindow!");
2465 NS_ASSERTION(aOpener
|| !aOriginalOpener
,
2466 "Shouldn't set mHadOriginalOpener if aOpener is null");
2468 mOpener
= do_GetWeakReference(aOpener
);
2469 NS_ASSERTION(mOpener
|| !aOpener
, "Opener must support weak references!");
2471 if (aOriginalOpener
) {
2472 mHadOriginalOpener
= PR_TRUE
;
2476 mSetOpenerWindowCalled
= PR_TRUE
;
2481 nsGlobalWindow::UpdateParentTarget()
2483 nsCOMPtr
<nsIFrameLoaderOwner
> flo
= do_QueryInterface(mChromeEventHandler
);
2485 nsRefPtr
<nsFrameLoader
> fl
= flo
->GetFrameLoader();
2487 mParentTarget
= fl
->GetTabChildGlobalAsEventTarget();
2490 if (!mParentTarget
) {
2491 mParentTarget
= mChromeEventHandler
;
2496 nsGlobalWindow::GetIsTabModalPromptAllowed()
2498 PRBool allowTabModal
= PR_TRUE
;
2500 nsCOMPtr
<nsIContentViewer
> cv
;
2501 mDocShell
->GetContentViewer(getter_AddRefs(cv
));
2502 nsCOMPtr
<nsIContentViewer_MOZILLA_2_0_BRANCH
> cv2
= do_QueryInterface(cv
);
2504 cv2
->GetIsTabModalPromptAllowed(&allowTabModal
);
2507 return allowTabModal
;
2511 nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor
& aVisitor
)
2513 NS_PRECONDITION(IsInnerWindow(), "PreHandleEvent is used on outer window!?");
2514 static PRUint32 count
= 0;
2515 PRUint32 msg
= aVisitor
.mEvent
->message
;
2517 aVisitor
.mCanHandle
= PR_TRUE
;
2518 aVisitor
.mForceContentDispatch
= PR_TRUE
; //FIXME! Bug 329119
2519 if ((msg
== NS_MOUSE_MOVE
) && gEntropyCollector
) {
2520 //Chances are this counter will overflow during the life of the
2521 //process, but that's OK for our case. Means we get a little
2523 if (count
++ % 100 == 0) {
2524 //Since the high bits seem to be zero's most of the time,
2525 //let's only take the lowest half of the point structure.
2528 myCoord
[0] = aVisitor
.mEvent
->refPoint
.x
;
2529 myCoord
[1] = aVisitor
.mEvent
->refPoint
.y
;
2530 gEntropyCollector
->RandomUpdate((void*)myCoord
, sizeof(myCoord
));
2531 gEntropyCollector
->RandomUpdate((void*)&(aVisitor
.mEvent
->time
),
2534 } else if (msg
== NS_RESIZE_EVENT
) {
2535 mIsHandlingResizeEvent
= PR_TRUE
;
2536 } else if (msg
== NS_MOUSE_BUTTON_DOWN
&&
2537 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2538 gMouseDown
= PR_TRUE
;
2539 } else if (msg
== NS_MOUSE_BUTTON_UP
&&
2540 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2541 gMouseDown
= PR_FALSE
;
2542 if (gDragServiceDisabled
) {
2543 nsCOMPtr
<nsIDragService
> ds
=
2544 do_GetService("@mozilla.org/widget/dragservice;1");
2546 gDragServiceDisabled
= PR_FALSE
;
2552 aVisitor
.mParentTarget
= GetParentTarget();
2557 nsGlobalWindow::DialogOpenAttempted()
2559 nsGlobalWindow
*topWindow
= GetTop();
2561 NS_ERROR("DialogOpenAttempted() called without a top window?");
2566 topWindow
= topWindow
->GetCurrentInnerWindowInternal();
2568 topWindow
->mLastDialogQuitTime
.IsNull() ||
2569 nsContentUtils::IsCallerTrustedForCapability("UniversalXPConnect")) {
2573 TimeDuration
dialogDuration(TimeStamp::Now() -
2574 topWindow
->mLastDialogQuitTime
);
2576 if (dialogDuration
.ToSeconds() <
2577 nsContentUtils::GetIntPref("dom.successive_dialog_time_limit",
2578 SUCCESSIVE_DIALOG_TIME_LIMIT
)) {
2579 topWindow
->mDialogAbuseCount
++;
2581 return (topWindow
->GetPopupControlState() > openAllowed
||
2582 topWindow
->mDialogAbuseCount
> MAX_DIALOG_COUNT
);
2585 topWindow
->mDialogAbuseCount
= 0;
2591 nsGlobalWindow::AreDialogsBlocked()
2593 nsGlobalWindow
*topWindow
= GetTop();
2595 NS_ASSERTION(!mDocShell
, "AreDialogsBlocked() called without a top window?");
2600 topWindow
= topWindow
->GetCurrentInnerWindowInternal();
2602 return !topWindow
||
2603 (topWindow
->mDialogDisabled
&&
2604 (topWindow
->GetPopupControlState() > openAllowed
||
2605 topWindow
->mDialogAbuseCount
>= MAX_DIALOG_COUNT
));
2609 nsGlobalWindow::ConfirmDialogAllowed()
2611 FORWARD_TO_OUTER(ConfirmDialogAllowed
, (), NS_ERROR_NOT_INITIALIZED
);
2613 NS_ENSURE_TRUE(mDocShell
, false);
2614 nsCOMPtr
<nsIPromptService
> promptSvc
=
2615 do_GetService("@mozilla.org/embedcomp/prompt-service;1");
2617 if (!DialogOpenAttempted() || !promptSvc
) {
2621 // Reset popup state while opening a modal dialog, and firing events
2622 // about the dialog, to prevent the current state from being active
2623 // the whole time a modal dialog is open.
2624 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
2626 PRBool disableDialog
= PR_FALSE
;
2627 nsXPIDLString label
, title
;
2628 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
2629 "ScriptDialogLabel", label
);
2630 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
2631 "ScriptDialogPreventTitle", title
);
2632 promptSvc
->Confirm(this, title
.get(), label
.get(), &disableDialog
);
2633 if (disableDialog
) {
2634 PreventFurtherDialogs();
2642 nsGlobalWindow::PreventFurtherDialogs()
2644 nsGlobalWindow
*topWindow
= GetTop();
2646 NS_ERROR("PreventFurtherDialogs() called without a top window?");
2651 topWindow
= topWindow
->GetCurrentInnerWindowInternal();
2654 topWindow
->mDialogDisabled
= PR_TRUE
;
2658 nsGlobalWindow::PostHandleEvent(nsEventChainPostVisitor
& aVisitor
)
2660 NS_PRECONDITION(IsInnerWindow(), "PostHandleEvent is used on outer window!?");
2662 // Return early if there is nothing to do.
2663 switch (aVisitor
.mEvent
->message
) {
2664 case NS_RESIZE_EVENT
:
2665 case NS_PAGE_UNLOAD
:
2672 /* mChromeEventHandler and mContext go dangling in the middle of this
2673 function under some circumstances (events that destroy the window)
2674 without this addref. */
2675 nsCOMPtr
<nsPIDOMEventTarget
> kungFuDeathGrip1(mChromeEventHandler
);
2676 nsCOMPtr
<nsIScriptContext
> kungFuDeathGrip2(GetContextInternal());
2678 if (aVisitor
.mEvent
->message
== NS_RESIZE_EVENT
) {
2679 mIsHandlingResizeEvent
= PR_FALSE
;
2680 } else if (aVisitor
.mEvent
->message
== NS_PAGE_UNLOAD
&&
2681 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2682 // Execute bindingdetached handlers before we tear ourselves
2685 NS_ASSERTION(mDoc
, "Must have doc");
2686 mDoc
->BindingManager()->ExecuteDetachedHandlers();
2688 mIsDocumentLoaded
= PR_FALSE
;
2689 } else if (aVisitor
.mEvent
->message
== NS_LOAD
&&
2690 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2691 // This is page load event since load events don't propagate to |window|.
2692 // @see nsDocument::PreHandleEvent.
2693 mIsDocumentLoaded
= PR_TRUE
;
2695 nsCOMPtr
<nsIContent
> content(do_QueryInterface(GetFrameElementInternal()));
2696 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
=
2697 do_QueryInterface(GetDocShell());
2699 PRInt32 itemType
= nsIDocShellTreeItem::typeChrome
;
2702 treeItem
->GetItemType(&itemType
);
2705 if (content
&& GetParentInternal() &&
2706 itemType
!= nsIDocShellTreeItem::typeChrome
) {
2707 // If we're not in chrome, or at a chrome boundary, fire the
2708 // onload event for the frame element.
2710 nsEventStatus status
= nsEventStatus_eIgnore
;
2711 nsEvent
event(NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
), NS_LOAD
);
2712 event
.flags
|= NS_EVENT_FLAG_CANT_BUBBLE
;
2714 // Most of the time we could get a pres context to pass in here,
2715 // but not always (i.e. if this window is not shown there won't
2716 // be a pres context available). Since we're not firing a GUI
2717 // event we don't need a pres context anyway so we just pass
2718 // null as the pres context all the time here.
2720 nsEventDispatcher::Dispatch(content
, nsnull
, &event
, nsnull
, &status
);
2728 nsGlobalWindow::DispatchDOMEvent(nsEvent
* aEvent
,
2729 nsIDOMEvent
* aDOMEvent
,
2730 nsPresContext
* aPresContext
,
2731 nsEventStatus
* aEventStatus
)
2734 nsEventDispatcher::DispatchDOMEvent(static_cast<nsPIDOMWindow
*>(this),
2735 aEvent
, aDOMEvent
, aPresContext
,
2740 nsGlobalWindow::OnFinalize(PRUint32 aLangID
, void *aObject
)
2742 NS_ASSERTION(aLangID
== nsIProgrammingLanguage::JAVASCRIPT
,
2743 "We don't support this language ID");
2745 if (aObject
== mJSObject
) {
2751 nsGlobalWindow::SetScriptsEnabled(PRBool aEnabled
, PRBool aFireTimeouts
)
2753 FORWARD_TO_INNER_VOID(SetScriptsEnabled
, (aEnabled
, aFireTimeouts
));
2755 if (aEnabled
&& aFireTimeouts
) {
2756 // Scripts are enabled (again?) on this context, run timeouts that
2757 // fired on this context while scripts were disabled.
2758 void (nsGlobalWindow::*run
)() = &nsGlobalWindow::RunTimeout
;
2759 NS_DispatchToCurrentThread(NS_NewRunnableMethod(this, run
));
2764 nsGlobalWindow::SetArguments(nsIArray
*aArguments
, nsIPrincipal
*aOrigin
)
2766 FORWARD_TO_OUTER(SetArguments
, (aArguments
, aOrigin
),
2767 NS_ERROR_NOT_INITIALIZED
);
2769 // Hold on to the arguments so that we can re-set them once the next
2770 // document is loaded.
2771 mArguments
= aArguments
;
2772 mArgumentsOrigin
= aOrigin
;
2774 nsGlobalWindow
*currentInner
= GetCurrentInnerWindowInternal();
2776 if (!mIsModalContentWindow
) {
2777 mArgumentsLast
= aArguments
;
2778 } else if (currentInner
) {
2779 // SetArguments() is being called on a modal content window that
2780 // already has an inner window. This can happen when loading
2781 // javascript: URIs as modal content dialogs. In this case, we'll
2782 // set up the dialog window, both inner and outer, before we call
2783 // SetArguments() on the window, so to deal with that, make sure
2784 // here that the arguments are propagated to the inner window.
2786 currentInner
->mArguments
= aArguments
;
2787 currentInner
->mArgumentsOrigin
= aOrigin
;
2790 return currentInner
?
2791 currentInner
->DefineArgumentsProperty(aArguments
) : NS_OK
;
2795 nsGlobalWindow::DefineArgumentsProperty(nsIArray
*aArguments
)
2798 nsIScriptContext
*ctx
= GetOuterWindowInternal()->mContext
;
2799 NS_ENSURE_TRUE(aArguments
&& ctx
&&
2800 (cx
= (JSContext
*)ctx
->GetNativeContext()),
2801 NS_ERROR_NOT_INITIALIZED
);
2803 if (mIsModalContentWindow
) {
2804 // Modal content windows don't have an "arguments" property, they
2805 // have a "dialogArguments" property which is handled
2806 // separately. See nsWindowSH::NewResolve().
2811 return GetContextInternal()->SetProperty(mJSObject
, "arguments", aArguments
);
2814 //*****************************************************************************
2815 // nsGlobalWindow::nsIScriptObjectPrincipal
2816 //*****************************************************************************
2819 nsGlobalWindow::GetPrincipal()
2822 // If we have a document, get the principal from the document
2823 return mDoc
->NodePrincipal();
2826 if (mDocumentPrincipal
) {
2827 return mDocumentPrincipal
;
2830 // If we don't have a principal and we don't have a document we
2831 // ask the parent window for the principal. This can happen when
2832 // loading a frameset that has a <frame src="javascript:xxx">, in
2833 // that case the global window is used in JS before we've loaded
2834 // a document into the window.
2836 nsCOMPtr
<nsIScriptObjectPrincipal
> objPrincipal
=
2837 do_QueryInterface(GetParentInternal());
2840 return objPrincipal
->GetPrincipal();
2846 //*****************************************************************************
2847 // nsGlobalWindow::nsIDOMWindow
2848 //*****************************************************************************
2851 nsGlobalWindow::GetDocument(nsIDOMDocument
** aDocument
)
2853 // This method *should* forward calls to the outer window, but since
2854 // there's nothing here that *depends* on anything in the outer
2855 // (GetDocShell() eliminates that dependency), we won't do that to
2856 // avoid the extra virtual function call.
2858 // lazily instantiate an about:blank document if necessary, and if
2859 // we have what it takes to do so. Note that domdoc here is the same
2860 // thing as our mDocument, but we don't have to explicitly set the
2861 // member variable because the docshell has already called
2862 // SetNewDocument().
2863 nsIDocShell
*docShell
;
2864 if (!mDocument
&& (docShell
= GetDocShell()))
2865 nsCOMPtr
<nsIDOMDocument
> domdoc(do_GetInterface(docShell
));
2867 NS_IF_ADDREF(*aDocument
= mDocument
);
2872 //*****************************************************************************
2873 // nsGlobalWindow::nsIDOMWindowInternal
2874 //*****************************************************************************
2877 nsGlobalWindow::GetWindow(nsIDOMWindowInternal
** aWindow
)
2879 FORWARD_TO_OUTER(GetWindow
, (aWindow
), NS_ERROR_NOT_INITIALIZED
);
2881 *aWindow
= static_cast<nsIDOMWindowInternal
*>(this);
2882 NS_ADDREF(*aWindow
);
2887 nsGlobalWindow::GetSelf(nsIDOMWindowInternal
** aWindow
)
2889 FORWARD_TO_OUTER(GetSelf
, (aWindow
), NS_ERROR_NOT_INITIALIZED
);
2891 *aWindow
= static_cast<nsIDOMWindowInternal
*>(this);
2892 NS_ADDREF(*aWindow
);
2897 nsGlobalWindow::GetNavigator(nsIDOMNavigator
** aNavigator
)
2899 FORWARD_TO_OUTER(GetNavigator
, (aNavigator
), NS_ERROR_NOT_INITIALIZED
);
2901 *aNavigator
= nsnull
;
2904 mNavigator
= new nsNavigator(mDocShell
);
2906 return NS_ERROR_OUT_OF_MEMORY
;
2910 NS_ADDREF(*aNavigator
= mNavigator
);
2916 nsGlobalWindow::GetScreen(nsIDOMScreen
** aScreen
)
2918 FORWARD_TO_OUTER(GetScreen
, (aScreen
), NS_ERROR_NOT_INITIALIZED
);
2922 if (!mScreen
&& mDocShell
) {
2923 mScreen
= new nsScreen(mDocShell
);
2925 return NS_ERROR_OUT_OF_MEMORY
;
2929 NS_IF_ADDREF(*aScreen
= mScreen
);
2935 nsGlobalWindow::GetHistory(nsIDOMHistory
** aHistory
)
2937 FORWARD_TO_INNER(GetHistory
, (aHistory
), NS_ERROR_NOT_INITIALIZED
);
2942 mHistory
= new nsHistory(this);
2944 return NS_ERROR_OUT_OF_MEMORY
;
2948 NS_IF_ADDREF(*aHistory
= mHistory
);
2953 nsGlobalWindow::GetParent(nsIDOMWindow
** aParent
)
2955 FORWARD_TO_OUTER(GetParent
, (aParent
), NS_ERROR_NOT_INITIALIZED
);
2961 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
2962 NS_ENSURE_TRUE(docShellAsItem
, NS_ERROR_FAILURE
);
2964 nsCOMPtr
<nsIDocShellTreeItem
> parent
;
2965 docShellAsItem
->GetSameTypeParent(getter_AddRefs(parent
));
2968 nsCOMPtr
<nsIScriptGlobalObject
> globalObject(do_GetInterface(parent
));
2969 NS_ENSURE_SUCCESS(CallQueryInterface(globalObject
.get(), aParent
),
2973 *aParent
= static_cast<nsIDOMWindowInternal
*>(this);
2974 NS_ADDREF(*aParent
);
2980 nsGlobalWindow::GetTop(nsIDOMWindow
** aTop
)
2982 FORWARD_TO_OUTER(GetTop
, (aTop
), NS_ERROR_NOT_INITIALIZED
);
2986 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
2987 nsCOMPtr
<nsIDocShellTreeItem
> root
;
2988 docShellAsItem
->GetSameTypeRootTreeItem(getter_AddRefs(root
));
2991 nsCOMPtr
<nsIDOMWindow
> top(do_GetInterface(root
));
3000 nsGlobalWindow::GetContent(nsIDOMWindow
** aContent
)
3002 FORWARD_TO_OUTER(GetContent
, (aContent
), NS_ERROR_NOT_INITIALIZED
);
3006 nsCOMPtr
<nsIDocShellTreeItem
> primaryContent
;
3008 if (!nsContentUtils::IsCallerChrome()) {
3009 // If we're called by non-chrome code, make sure we don't return
3010 // the primary content window if the calling tab is hidden. In
3011 // such a case we return the same-type root in the hidden tab,
3012 // which is "good enough", for now.
3013 nsCOMPtr
<nsIBaseWindow
> baseWin(do_QueryInterface(mDocShell
));
3016 PRBool visible
= PR_FALSE
;
3017 baseWin
->GetVisibility(&visible
);
3020 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(do_QueryInterface(mDocShell
));
3022 treeItem
->GetSameTypeRootTreeItem(getter_AddRefs(primaryContent
));
3027 if (!primaryContent
) {
3028 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
3029 GetTreeOwner(getter_AddRefs(treeOwner
));
3030 NS_ENSURE_TRUE(treeOwner
, NS_ERROR_FAILURE
);
3032 treeOwner
->GetPrimaryContentShell(getter_AddRefs(primaryContent
));
3035 nsCOMPtr
<nsIDOMWindowInternal
> domWindow(do_GetInterface(primaryContent
));
3036 NS_IF_ADDREF(*aContent
= domWindow
);
3042 nsGlobalWindow::GetPrompter(nsIPrompt
** aPrompt
)
3044 FORWARD_TO_OUTER(GetPrompter
, (aPrompt
), NS_ERROR_NOT_INITIALIZED
);
3047 return NS_ERROR_FAILURE
;
3049 nsCOMPtr
<nsIPrompt
> prompter(do_GetInterface(mDocShell
));
3050 NS_ENSURE_TRUE(prompter
, NS_ERROR_NO_INTERFACE
);
3052 NS_ADDREF(*aPrompt
= prompter
);
3057 nsGlobalWindow::GetMenubar(nsIDOMBarProp
** aMenubar
)
3059 FORWARD_TO_OUTER(GetMenubar
, (aMenubar
), NS_ERROR_NOT_INITIALIZED
);
3064 mMenubar
= new nsMenubarProp();
3066 return NS_ERROR_OUT_OF_MEMORY
;
3069 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3070 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3072 mMenubar
->SetWebBrowserChrome(browserChrome
);
3075 NS_ADDREF(*aMenubar
= mMenubar
);
3081 nsGlobalWindow::GetToolbar(nsIDOMBarProp
** aToolbar
)
3083 FORWARD_TO_OUTER(GetToolbar
, (aToolbar
), NS_ERROR_NOT_INITIALIZED
);
3088 mToolbar
= new nsToolbarProp();
3090 return NS_ERROR_OUT_OF_MEMORY
;
3093 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3094 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3096 mToolbar
->SetWebBrowserChrome(browserChrome
);
3099 NS_ADDREF(*aToolbar
= mToolbar
);
3105 nsGlobalWindow::GetLocationbar(nsIDOMBarProp
** aLocationbar
)
3107 FORWARD_TO_OUTER(GetLocationbar
, (aLocationbar
), NS_ERROR_NOT_INITIALIZED
);
3109 *aLocationbar
= nsnull
;
3111 if (!mLocationbar
) {
3112 mLocationbar
= new nsLocationbarProp();
3113 if (!mLocationbar
) {
3114 return NS_ERROR_OUT_OF_MEMORY
;
3117 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3118 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3120 mLocationbar
->SetWebBrowserChrome(browserChrome
);
3123 NS_ADDREF(*aLocationbar
= mLocationbar
);
3129 nsGlobalWindow::GetPersonalbar(nsIDOMBarProp
** aPersonalbar
)
3131 FORWARD_TO_OUTER(GetPersonalbar
, (aPersonalbar
), NS_ERROR_NOT_INITIALIZED
);
3133 *aPersonalbar
= nsnull
;
3135 if (!mPersonalbar
) {
3136 mPersonalbar
= new nsPersonalbarProp();
3137 if (!mPersonalbar
) {
3138 return NS_ERROR_OUT_OF_MEMORY
;
3141 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3142 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3144 mPersonalbar
->SetWebBrowserChrome(browserChrome
);
3147 NS_ADDREF(*aPersonalbar
= mPersonalbar
);
3153 nsGlobalWindow::GetStatusbar(nsIDOMBarProp
** aStatusbar
)
3155 FORWARD_TO_OUTER(GetStatusbar
, (aStatusbar
), NS_ERROR_NOT_INITIALIZED
);
3157 *aStatusbar
= nsnull
;
3160 mStatusbar
= new nsStatusbarProp();
3162 return NS_ERROR_OUT_OF_MEMORY
;
3165 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3166 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3168 mStatusbar
->SetWebBrowserChrome(browserChrome
);
3171 NS_ADDREF(*aStatusbar
= mStatusbar
);
3177 nsGlobalWindow::GetScrollbars(nsIDOMBarProp
** aScrollbars
)
3179 FORWARD_TO_OUTER(GetScrollbars
, (aScrollbars
), NS_ERROR_NOT_INITIALIZED
);
3181 *aScrollbars
= nsnull
;
3184 mScrollbars
= new nsScrollbarsProp(this);
3186 return NS_ERROR_OUT_OF_MEMORY
;
3189 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3190 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3192 mScrollbars
->SetWebBrowserChrome(browserChrome
);
3195 NS_ADDREF(*aScrollbars
= mScrollbars
);
3201 nsGlobalWindow::GetClosed(PRBool
* aClosed
)
3203 FORWARD_TO_OUTER(GetClosed
, (aClosed
), NS_ERROR_NOT_INITIALIZED
);
3205 // If someone called close(), or if we don't have a docshell, we're
3207 *aClosed
= mIsClosed
|| !mDocShell
;
3213 nsGlobalWindow::GetFrames(nsIDOMWindowCollection
** aFrames
)
3215 FORWARD_TO_OUTER(GetFrames
, (aFrames
), NS_ERROR_NOT_INITIALIZED
);
3219 if (!mFrames
&& mDocShell
) {
3220 mFrames
= new nsDOMWindowList(mDocShell
);
3222 return NS_ERROR_OUT_OF_MEMORY
;
3226 *aFrames
= static_cast<nsIDOMWindowCollection
*>(mFrames
);
3227 NS_IF_ADDREF(*aFrames
);
3232 nsGlobalWindow::GetApplicationCache(nsIDOMOfflineResourceList
**aApplicationCache
)
3234 FORWARD_TO_INNER(GetApplicationCache
, (aApplicationCache
), NS_ERROR_UNEXPECTED
);
3236 NS_ENSURE_ARG_POINTER(aApplicationCache
);
3238 if (!mApplicationCache
) {
3239 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(GetDocShell()));
3241 return NS_ERROR_FAILURE
;
3244 nsCOMPtr
<nsIURI
> uri
;
3245 nsresult rv
= webNav
->GetCurrentURI(getter_AddRefs(uri
));
3246 NS_ENSURE_SUCCESS(rv
, rv
);
3248 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(mDocument
);
3249 nsCOMPtr
<nsIURI
> manifestURI
;
3250 nsContentUtils::GetOfflineAppManifest(doc
, getter_AddRefs(manifestURI
));
3252 nsIScriptContext
* scriptContext
= GetContext();
3253 NS_ENSURE_STATE(scriptContext
);
3255 nsRefPtr
<nsDOMOfflineResourceList
> applicationCache
=
3256 new nsDOMOfflineResourceList(manifestURI
, uri
, this, scriptContext
);
3257 NS_ENSURE_TRUE(applicationCache
, NS_ERROR_OUT_OF_MEMORY
);
3259 applicationCache
->Init();
3261 mApplicationCache
= applicationCache
;
3264 NS_IF_ADDREF(*aApplicationCache
= mApplicationCache
);
3270 nsGlobalWindow::CreateBlobURL(nsIDOMBlob
* aBlob
, nsAString
& aURL
)
3272 return NS_ERROR_NOT_IMPLEMENTED
;
3276 nsGlobalWindow::RevokeBlobURL(const nsAString
& aURL
)
3278 return NS_ERROR_NOT_IMPLEMENTED
;
3282 nsGlobalWindow::GetCrypto(nsIDOMCrypto
** aCrypto
)
3284 #ifdef MOZ_DISABLE_DOMCRYPTO
3285 return NS_ERROR_NOT_IMPLEMENTED
;
3287 FORWARD_TO_OUTER(GetCrypto
, (aCrypto
), NS_ERROR_NOT_INITIALIZED
);
3290 mCrypto
= do_CreateInstance(kCryptoContractID
);
3293 NS_IF_ADDREF(*aCrypto
= mCrypto
);
3300 nsGlobalWindow::GetPkcs11(nsIDOMPkcs11
** aPkcs11
)
3307 nsGlobalWindow::GetControllers(nsIControllers
** aResult
)
3309 FORWARD_TO_OUTER(GetControllers
, (aResult
), NS_ERROR_NOT_INITIALIZED
);
3311 if (!mControllers
) {
3313 mControllers
= do_CreateInstance(kXULControllersCID
, &rv
);
3314 NS_ENSURE_SUCCESS(rv
, rv
);
3316 // Add in the default controller
3317 nsCOMPtr
<nsIController
> controller
= do_CreateInstance(
3318 NS_WINDOWCONTROLLER_CONTRACTID
, &rv
);
3319 NS_ENSURE_SUCCESS(rv
, rv
);
3321 mControllers
->InsertControllerAt(0, controller
);
3322 nsCOMPtr
<nsIControllerContext
> controllerContext
= do_QueryInterface(controller
);
3323 if (!controllerContext
) return NS_ERROR_FAILURE
;
3325 controllerContext
->SetCommandContext(static_cast<nsIDOMWindow
*>(this));
3328 *aResult
= mControllers
;
3329 NS_ADDREF(*aResult
);
3334 nsGlobalWindow::GetOpener(nsIDOMWindowInternal
** aOpener
)
3336 FORWARD_TO_OUTER(GetOpener
, (aOpener
), NS_ERROR_NOT_INITIALIZED
);
3340 nsCOMPtr
<nsPIDOMWindow
> opener
= do_QueryReferent(mOpener
);
3345 // First, check if we were called from a privileged chrome script
3346 if (nsContentUtils::IsCallerTrustedForRead()) {
3347 NS_ADDREF(*aOpener
= opener
);
3351 nsCOMPtr
<nsPIDOMWindow
> openerPwin(do_QueryInterface(opener
));
3356 // First, ensure that we're not handing back a chrome window.
3357 nsGlobalWindow
*win
= static_cast<nsGlobalWindow
*>(openerPwin
.get());
3358 if (win
->IsChromeWindow()) {
3362 // We don't want to reveal the opener if the opener is a mail window,
3363 // because opener can be used to spoof the contents of a message (bug 105050).
3364 // So, we look in the opener's root docshell to see if it's a mail window.
3365 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem
=
3366 do_QueryInterface(openerPwin
->GetDocShell());
3368 if (docShellAsItem
) {
3369 nsCOMPtr
<nsIDocShellTreeItem
> openerRootItem
;
3370 docShellAsItem
->GetRootTreeItem(getter_AddRefs(openerRootItem
));
3371 nsCOMPtr
<nsIDocShell
> openerRootDocShell(do_QueryInterface(openerRootItem
));
3372 if (openerRootDocShell
) {
3374 nsresult rv
= openerRootDocShell
->GetAppType(&appType
);
3375 if (NS_SUCCEEDED(rv
) && appType
!= nsIDocShell::APP_TYPE_MAIL
) {
3381 NS_IF_ADDREF(*aOpener
);
3386 nsGlobalWindow::SetOpener(nsIDOMWindowInternal
* aOpener
)
3388 // check if we were called from a privileged chrome script.
3389 // If not, opener is settable only to null.
3390 if (aOpener
&& !nsContentUtils::IsCallerTrustedForWrite()) {
3394 SetOpenerWindow(aOpener
, PR_FALSE
);
3400 nsGlobalWindow::GetStatus(nsAString
& aStatus
)
3402 FORWARD_TO_OUTER(GetStatus
, (aStatus
), NS_ERROR_NOT_INITIALIZED
);
3409 nsGlobalWindow::SetStatus(const nsAString
& aStatus
)
3411 FORWARD_TO_OUTER(SetStatus
, (aStatus
), NS_ERROR_NOT_INITIALIZED
);
3414 * If caller is not chrome and dom.disable_window_status_change is true,
3415 * prevent setting window.status by exiting early
3418 if (!CanSetProperty("dom.disable_window_status_change")) {
3424 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3425 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3427 browserChrome
->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT
,
3428 PromiseFlatString(aStatus
).get());
3435 nsGlobalWindow::GetDefaultStatus(nsAString
& aDefaultStatus
)
3437 FORWARD_TO_OUTER(GetDefaultStatus
, (aDefaultStatus
),
3438 NS_ERROR_NOT_INITIALIZED
);
3440 aDefaultStatus
= mDefaultStatus
;
3445 nsGlobalWindow::SetDefaultStatus(const nsAString
& aDefaultStatus
)
3447 FORWARD_TO_OUTER(SetDefaultStatus
, (aDefaultStatus
),
3448 NS_ERROR_NOT_INITIALIZED
);
3451 * If caller is not chrome and dom.disable_window_status_change is true,
3452 * prevent setting window.defaultStatus by exiting early
3455 if (!CanSetProperty("dom.disable_window_status_change")) {
3459 mDefaultStatus
= aDefaultStatus
;
3461 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3462 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3463 if (browserChrome
) {
3464 browserChrome
->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT_DEFAULT
,
3465 PromiseFlatString(aDefaultStatus
).get());
3472 nsGlobalWindow::GetName(nsAString
& aName
)
3474 FORWARD_TO_OUTER(GetName
, (aName
), NS_ERROR_NOT_INITIALIZED
);
3477 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
3479 docShellAsItem
->GetName(getter_Copies(name
));
3486 nsGlobalWindow::SetName(const nsAString
& aName
)
3488 FORWARD_TO_OUTER(SetName
, (aName
), NS_ERROR_NOT_INITIALIZED
);
3490 nsresult result
= NS_OK
;
3491 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
3493 result
= docShellAsItem
->SetName(PromiseFlatString(aName
).get());
3497 // Helper functions used by many methods below.
3499 nsGlobalWindow::DevToCSSIntPixels(PRInt32 px
)
3502 return px
; // assume 1:1
3504 nsRefPtr
<nsPresContext
> presContext
;
3505 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3509 return presContext
->DevPixelsToIntCSSPixels(px
);
3513 nsGlobalWindow::CSSToDevIntPixels(PRInt32 px
)
3516 return px
; // assume 1:1
3518 nsRefPtr
<nsPresContext
> presContext
;
3519 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3523 return presContext
->CSSPixelsToDevPixels(px
);
3527 nsGlobalWindow::DevToCSSIntPixels(nsIntSize px
)
3530 return px
; // assume 1:1
3532 nsRefPtr
<nsPresContext
> presContext
;
3533 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3538 presContext
->DevPixelsToIntCSSPixels(px
.width
),
3539 presContext
->DevPixelsToIntCSSPixels(px
.height
));
3543 nsGlobalWindow::CSSToDevIntPixels(nsIntSize px
)
3546 return px
; // assume 1:1
3548 nsRefPtr
<nsPresContext
> presContext
;
3549 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3554 presContext
->CSSPixelsToDevPixels(px
.width
),
3555 presContext
->CSSPixelsToDevPixels(px
.height
));
3560 nsGlobalWindow::GetInnerWidth(PRInt32
* aInnerWidth
)
3562 FORWARD_TO_OUTER(GetInnerWidth
, (aInnerWidth
), NS_ERROR_NOT_INITIALIZED
);
3564 NS_ENSURE_STATE(mDocShell
);
3566 EnsureSizeUpToDate();
3568 nsRefPtr
<nsPresContext
> presContext
;
3569 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3572 nsRect shellArea
= presContext
->GetVisibleArea();
3573 *aInnerWidth
= nsPresContext::AppUnitsToIntCSSPixels(shellArea
.width
);
3582 nsGlobalWindow::SetInnerWidth(PRInt32 aInnerWidth
)
3584 FORWARD_TO_OUTER(SetInnerWidth
, (aInnerWidth
), NS_ERROR_NOT_INITIALIZED
);
3586 NS_ENSURE_STATE(mDocShell
);
3589 * If caller is not chrome and the user has not explicitly exempted the site,
3590 * prevent setting window.innerWidth by exiting early
3592 if (!CanMoveResizeWindows() || IsFrame()) {
3596 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&aInnerWidth
, nsnull
),
3600 nsRefPtr
<nsIPresShell
> presShell
;
3601 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
3602 nsCOMPtr
<nsIPresShell_MOZILLA_2_0_BRANCH
> presShell20
=
3603 do_QueryInterface(presShell
);
3605 if (presShell20
&& presShell20
->GetIsViewportOverridden())
3610 nsRefPtr
<nsPresContext
> presContext
;
3611 presContext
= presShell
->GetPresContext();
3613 nsRect shellArea
= presContext
->GetVisibleArea();
3614 height
= shellArea
.height
;
3615 width
= nsPresContext::CSSPixelsToAppUnits(aInnerWidth
);
3616 return SetCSSViewportWidthAndHeight(width
, height
);
3623 nsCOMPtr
<nsIBaseWindow
> docShellAsWin(do_QueryInterface(mDocShell
));
3624 docShellAsWin
->GetSize(&width
, &height
);
3625 width
= CSSToDevIntPixels(aInnerWidth
);
3626 return SetDocShellWidthAndHeight(width
, height
);
3631 nsGlobalWindow::GetInnerHeight(PRInt32
* aInnerHeight
)
3633 FORWARD_TO_OUTER(GetInnerHeight
, (aInnerHeight
), NS_ERROR_NOT_INITIALIZED
);
3635 NS_ENSURE_STATE(mDocShell
);
3637 EnsureSizeUpToDate();
3639 nsRefPtr
<nsPresContext
> presContext
;
3640 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3643 nsRect shellArea
= presContext
->GetVisibleArea();
3644 *aInnerHeight
= nsPresContext::AppUnitsToIntCSSPixels(shellArea
.height
);
3652 nsGlobalWindow::SetInnerHeight(PRInt32 aInnerHeight
)
3654 FORWARD_TO_OUTER(SetInnerHeight
, (aInnerHeight
), NS_ERROR_NOT_INITIALIZED
);
3656 NS_ENSURE_STATE(mDocShell
);
3659 * If caller is not chrome and the user has not explicitly exempted the site,
3660 * prevent setting window.innerHeight by exiting early
3662 if (!CanMoveResizeWindows() || IsFrame()) {
3666 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(nsnull
, &aInnerHeight
),
3669 nsRefPtr
<nsIPresShell
> presShell
;
3670 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
3671 nsCOMPtr
<nsIPresShell_MOZILLA_2_0_BRANCH
> presShell20
=
3672 do_QueryInterface(presShell
);
3674 if (presShell20
&& presShell20
->GetIsViewportOverridden())
3679 nsRefPtr
<nsPresContext
> presContext
;
3680 presContext
= presShell
->GetPresContext();
3682 nsRect shellArea
= presContext
->GetVisibleArea();
3683 width
= shellArea
.width
;
3684 height
= nsPresContext::CSSPixelsToAppUnits(aInnerHeight
);
3685 return SetCSSViewportWidthAndHeight(width
, height
);
3692 nsCOMPtr
<nsIBaseWindow
> docShellAsWin(do_QueryInterface(mDocShell
));
3693 docShellAsWin
->GetSize(&width
, &height
);
3694 height
= CSSToDevIntPixels(aInnerHeight
);
3695 return SetDocShellWidthAndHeight(width
, height
);
3700 nsGlobalWindow::GetOuterSize(nsIntSize
* aSizeCSSPixels
)
3702 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3703 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3704 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3706 nsGlobalWindow
* rootWindow
=
3707 static_cast<nsGlobalWindow
*>(GetPrivateRoot());
3709 rootWindow
->FlushPendingNotifications(Flush_Layout
);
3712 nsIntSize sizeDevPixels
;
3713 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetSize(&sizeDevPixels
.width
,
3714 &sizeDevPixels
.height
),
3717 *aSizeCSSPixels
= DevToCSSIntPixels(sizeDevPixels
);
3722 nsGlobalWindow::GetOuterWidth(PRInt32
* aOuterWidth
)
3724 FORWARD_TO_OUTER(GetOuterWidth
, (aOuterWidth
), NS_ERROR_NOT_INITIALIZED
);
3726 nsIntSize sizeCSSPixels
;
3727 nsresult rv
= GetOuterSize(&sizeCSSPixels
);
3728 NS_ENSURE_SUCCESS(rv
, rv
);
3730 *aOuterWidth
= sizeCSSPixels
.width
;
3735 nsGlobalWindow::GetOuterHeight(PRInt32
* aOuterHeight
)
3737 FORWARD_TO_OUTER(GetOuterHeight
, (aOuterHeight
), NS_ERROR_NOT_INITIALIZED
);
3739 nsIntSize sizeCSSPixels
;
3740 nsresult rv
= GetOuterSize(&sizeCSSPixels
);
3741 NS_ENSURE_SUCCESS(rv
, rv
);
3743 *aOuterHeight
= sizeCSSPixels
.height
;
3748 nsGlobalWindow::SetOuterSize(PRInt32 aLengthCSSPixels
, PRBool aIsWidth
)
3751 * If caller is not chrome and the user has not explicitly exempted the site,
3752 * prevent setting window.outerWidth by exiting early
3755 if (!CanMoveResizeWindows() || IsFrame()) {
3759 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3760 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3761 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3763 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(
3764 aIsWidth
? &aLengthCSSPixels
: nsnull
,
3765 aIsWidth
? nsnull
: &aLengthCSSPixels
),
3768 PRInt32 width
, height
;
3769 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetSize(&width
, &height
), NS_ERROR_FAILURE
);
3771 PRInt32 lengthDevPixels
= CSSToDevIntPixels(aLengthCSSPixels
);
3773 width
= lengthDevPixels
;
3775 height
= lengthDevPixels
;
3777 return treeOwnerAsWin
->SetSize(width
, height
, PR_TRUE
);
3781 nsGlobalWindow::SetOuterWidth(PRInt32 aOuterWidth
)
3783 FORWARD_TO_OUTER(SetOuterWidth
, (aOuterWidth
), NS_ERROR_NOT_INITIALIZED
);
3785 return SetOuterSize(aOuterWidth
, PR_TRUE
);
3789 nsGlobalWindow::SetOuterHeight(PRInt32 aOuterHeight
)
3791 FORWARD_TO_OUTER(SetOuterHeight
, (aOuterHeight
), NS_ERROR_NOT_INITIALIZED
);
3793 return SetOuterSize(aOuterHeight
, PR_FALSE
);
3797 nsGlobalWindow::GetScreenX(PRInt32
* aScreenX
)
3799 FORWARD_TO_OUTER(GetScreenX
, (aScreenX
), NS_ERROR_NOT_INITIALIZED
);
3801 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3802 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3803 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3807 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3810 *aScreenX
= DevToCSSIntPixels(x
);
3815 nsGlobalWindow::GetInnerScreenRect()
3820 nsGlobalWindow
* rootWindow
=
3821 static_cast<nsGlobalWindow
*>(GetPrivateRoot());
3823 rootWindow
->FlushPendingNotifications(Flush_Layout
);
3826 nsCOMPtr
<nsIPresShell
> presShell
;
3827 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
3830 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
3834 return rootFrame
->GetScreenRectInAppUnits();
3838 nsGlobalWindow::GetMozInnerScreenX(float* aScreenX
)
3840 FORWARD_TO_OUTER(GetMozInnerScreenX
, (aScreenX
), NS_ERROR_NOT_INITIALIZED
);
3842 nsRect r
= GetInnerScreenRect();
3843 *aScreenX
= nsPresContext::AppUnitsToFloatCSSPixels(r
.x
);
3848 nsGlobalWindow::GetMozInnerScreenY(float* aScreenY
)
3850 FORWARD_TO_OUTER(GetMozInnerScreenY
, (aScreenY
), NS_ERROR_NOT_INITIALIZED
);
3852 nsRect r
= GetInnerScreenRect();
3853 *aScreenY
= nsPresContext::AppUnitsToFloatCSSPixels(r
.y
);
3858 nsGlobalWindow::GetMozPaintCount(PRUint64
* aResult
)
3860 FORWARD_TO_OUTER(GetMozPaintCount
, (aResult
), NS_ERROR_NOT_INITIALIZED
);
3867 nsCOMPtr
<nsIPresShell
> presShell
;
3868 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
3872 *aResult
= presShell
->GetPaintCount();
3877 nsGlobalWindow::MozRequestAnimationFrame(nsIAnimationFrameListener
* aListener
)
3879 FORWARD_TO_INNER(MozRequestAnimationFrame
, (aListener
),
3880 NS_ERROR_NOT_INITIALIZED
);
3886 mDoc
->ScheduleBeforePaintEvent(aListener
);
3891 nsGlobalWindow::GetMozAnimationStartTime(PRInt64
*aTime
)
3893 FORWARD_TO_INNER(GetMozAnimationStartTime
, (aTime
), NS_ERROR_NOT_INITIALIZED
);
3896 nsIPresShell
* presShell
= mDoc
->GetShell();
3898 *aTime
= presShell
->GetPresContext()->RefreshDriver()->
3899 MostRecentRefreshEpochTime() / PR_USEC_PER_MSEC
;
3904 // If all else fails, just be compatible with Date.now()
3905 *aTime
= JS_Now() / PR_USEC_PER_MSEC
;
3910 nsGlobalWindow::SetScreenX(PRInt32 aScreenX
)
3912 FORWARD_TO_OUTER(SetScreenX
, (aScreenX
), NS_ERROR_NOT_INITIALIZED
);
3915 * If caller is not chrome and the user has not explicitly exempted the site,
3916 * prevent setting window.screenX by exiting early
3919 if (!CanMoveResizeWindows() || IsFrame()) {
3923 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3924 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3925 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3927 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&aScreenX
, nsnull
),
3931 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3934 x
= CSSToDevIntPixels(aScreenX
);
3936 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(x
, y
),
3943 nsGlobalWindow::GetScreenY(PRInt32
* aScreenY
)
3945 FORWARD_TO_OUTER(GetScreenY
, (aScreenY
), NS_ERROR_NOT_INITIALIZED
);
3947 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3948 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3949 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3953 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3956 *aScreenY
= DevToCSSIntPixels(y
);
3961 nsGlobalWindow::SetScreenY(PRInt32 aScreenY
)
3963 FORWARD_TO_OUTER(SetScreenY
, (aScreenY
), NS_ERROR_NOT_INITIALIZED
);
3966 * If caller is not chrome and the user has not explicitly exempted the site,
3967 * prevent setting window.screenY by exiting early
3970 if (!CanMoveResizeWindows() || IsFrame()) {
3974 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3975 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3976 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3978 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(nsnull
, &aScreenY
),
3982 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3985 y
= CSSToDevIntPixels(aScreenY
);
3987 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(x
, y
),
3993 // NOTE: Arguments to this function should have values scaled to
3994 // CSS pixels, not device pixels.
3996 nsGlobalWindow::CheckSecurityWidthAndHeight(PRInt32
* aWidth
, PRInt32
* aHeight
)
3999 if (!nsContentUtils::IsCallerTrustedForWrite()) {
4000 // if attempting to resize the window, hide any open popups
4001 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
4002 nsContentUtils::HidePopupsInDocument(doc
);
4006 // This one is easy. Just ensure the variable is greater than 100;
4007 if ((aWidth
&& *aWidth
< 100) || (aHeight
&& *aHeight
< 100)) {
4008 // Check security state for use in determing window dimensions
4010 if (!nsContentUtils::IsCallerTrustedForWrite()) {
4012 if (aWidth
&& *aWidth
< 100) {
4015 if (aHeight
&& *aHeight
< 100) {
4024 // NOTE: Arguments to this function should have values in device pixels
4026 nsGlobalWindow::SetDocShellWidthAndHeight(PRInt32 aInnerWidth
, PRInt32 aInnerHeight
)
4028 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
4029 NS_ENSURE_TRUE(docShellAsItem
, NS_ERROR_FAILURE
);
4031 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
4032 docShellAsItem
->GetTreeOwner(getter_AddRefs(treeOwner
));
4033 NS_ENSURE_TRUE(treeOwner
, NS_ERROR_FAILURE
);
4035 NS_ENSURE_SUCCESS(treeOwner
->SizeShellTo(docShellAsItem
, aInnerWidth
, aInnerHeight
),
4041 // NOTE: Arguments to this function should have values in app units
4043 nsGlobalWindow::SetCSSViewportWidthAndHeight(nscoord aInnerWidth
, nscoord aInnerHeight
)
4045 nsRefPtr
<nsPresContext
> presContext
;
4046 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
4048 nsRect shellArea
= presContext
->GetVisibleArea();
4049 shellArea
.height
= aInnerHeight
;
4050 shellArea
.width
= aInnerWidth
;
4052 presContext
->SetVisibleArea(shellArea
);
4056 // NOTE: Arguments to this function should have values scaled to
4057 // CSS pixels, not device pixels.
4059 nsGlobalWindow::CheckSecurityLeftAndTop(PRInt32
* aLeft
, PRInt32
* aTop
)
4061 // This one is harder. We have to get the screen size and window dimensions.
4063 // Check security state for use in determing window dimensions
4065 if (!nsContentUtils::IsCallerTrustedForWrite()) {
4067 // if attempting to move the window, hide any open popups
4068 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
4069 nsContentUtils::HidePopupsInDocument(doc
);
4072 nsGlobalWindow
* rootWindow
=
4073 static_cast<nsGlobalWindow
*>(GetPrivateRoot());
4075 rootWindow
->FlushPendingNotifications(Flush_Layout
);
4078 nsCOMPtr
<nsIBaseWindow
> treeOwner
;
4079 GetTreeOwner(getter_AddRefs(treeOwner
));
4081 nsCOMPtr
<nsIDOMScreen
> screen
;
4082 GetScreen(getter_AddRefs(screen
));
4084 if (treeOwner
&& screen
) {
4085 PRInt32 screenLeft
, screenTop
, screenWidth
, screenHeight
;
4086 PRInt32 winLeft
, winTop
, winWidth
, winHeight
;
4088 // Get the window size
4089 treeOwner
->GetPositionAndSize(&winLeft
, &winTop
, &winWidth
, &winHeight
);
4091 // convert those values to CSS pixels
4092 // XXX four separate retrievals of the prescontext
4093 winLeft
= DevToCSSIntPixels(winLeft
);
4094 winTop
= DevToCSSIntPixels(winTop
);
4095 winWidth
= DevToCSSIntPixels(winWidth
);
4096 winHeight
= DevToCSSIntPixels(winHeight
);
4098 // Get the screen dimensions
4099 // XXX This should use nsIScreenManager once it's fully fleshed out.
4100 screen
->GetAvailLeft(&screenLeft
);
4101 screen
->GetAvailWidth(&screenWidth
);
4102 screen
->GetAvailHeight(&screenHeight
);
4103 #if defined(XP_MAC) || defined(XP_MACOSX)
4104 /* The mac's coordinate system is different from the assumed Windows'
4105 system. It offsets by the height of the menubar so that a window
4106 placed at (0,0) will be entirely visible. Unfortunately that
4107 correction is made elsewhere (in Widget) and the meaning of
4108 the Avail... coordinates is overloaded. Here we allow a window
4109 to be placed at (0,0) because it does make sense to do so.
4111 screen
->GetTop(&screenTop
);
4113 screen
->GetAvailTop(&screenTop
);
4117 if (screenLeft
+screenWidth
< *aLeft
+winWidth
)
4118 *aLeft
= screenLeft
+screenWidth
- winWidth
;
4119 if (screenLeft
> *aLeft
)
4120 *aLeft
= screenLeft
;
4123 if (screenTop
+screenHeight
< *aTop
+winHeight
)
4124 *aTop
= screenTop
+screenHeight
- winHeight
;
4125 if (screenTop
> *aTop
)
4140 nsGlobalWindow::GetPageXOffset(PRInt32
* aPageXOffset
)
4142 return GetScrollX(aPageXOffset
);
4146 nsGlobalWindow::GetPageYOffset(PRInt32
* aPageYOffset
)
4148 return GetScrollY(aPageYOffset
);
4152 nsGlobalWindow::GetScrollMaxXY(PRInt32
* aScrollMaxX
, PRInt32
* aScrollMaxY
)
4154 FORWARD_TO_OUTER(GetScrollMaxXY
, (aScrollMaxX
, aScrollMaxY
),
4155 NS_ERROR_NOT_INITIALIZED
);
4157 FlushPendingNotifications(Flush_Layout
);
4158 nsIScrollableFrame
*sf
= GetScrollFrame();
4162 nsRect scrollRange
= sf
->GetScrollRange();
4165 *aScrollMaxX
= NS_MAX(0,
4166 (PRInt32
)floor(nsPresContext::AppUnitsToFloatCSSPixels(scrollRange
.XMost())));
4168 *aScrollMaxY
= NS_MAX(0,
4169 (PRInt32
)floor(nsPresContext::AppUnitsToFloatCSSPixels(scrollRange
.YMost())));
4175 nsGlobalWindow::GetScrollMaxX(PRInt32
* aScrollMaxX
)
4177 NS_ENSURE_ARG_POINTER(aScrollMaxX
);
4179 return GetScrollMaxXY(aScrollMaxX
, nsnull
);
4183 nsGlobalWindow::GetScrollMaxY(PRInt32
* aScrollMaxY
)
4185 NS_ENSURE_ARG_POINTER(aScrollMaxY
);
4187 return GetScrollMaxXY(nsnull
, aScrollMaxY
);
4191 nsGlobalWindow::GetScrollXY(PRInt32
* aScrollX
, PRInt32
* aScrollY
,
4194 FORWARD_TO_OUTER(GetScrollXY
, (aScrollX
, aScrollY
, aDoFlush
),
4195 NS_ERROR_NOT_INITIALIZED
);
4198 FlushPendingNotifications(Flush_Layout
);
4200 EnsureSizeUpToDate();
4203 nsIScrollableFrame
*sf
= GetScrollFrame();
4207 nsPoint scrollPos
= sf
->GetScrollPosition();
4208 if (scrollPos
!= nsPoint(0,0) && !aDoFlush
) {
4209 // Oh, well. This is the expensive case -- the window is scrolled and we
4210 // didn't actually flush yet. Repeat, but with a flush, since the content
4211 // may get shorter and hence our scroll position may decrease.
4212 return GetScrollXY(aScrollX
, aScrollY
, PR_TRUE
);
4216 *aScrollX
= nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.x
);
4218 *aScrollY
= nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.y
);
4224 nsGlobalWindow::GetScrollX(PRInt32
* aScrollX
)
4226 NS_ENSURE_ARG_POINTER(aScrollX
);
4228 return GetScrollXY(aScrollX
, nsnull
, PR_FALSE
);
4232 nsGlobalWindow::GetScrollY(PRInt32
* aScrollY
)
4234 NS_ENSURE_ARG_POINTER(aScrollY
);
4236 return GetScrollXY(nsnull
, aScrollY
, PR_FALSE
);
4240 nsGlobalWindow::GetLength(PRUint32
* aLength
)
4242 nsCOMPtr
<nsIDOMWindowCollection
> frames
;
4243 if (NS_SUCCEEDED(GetFrames(getter_AddRefs(frames
))) && frames
) {
4244 return frames
->GetLength(aLength
);
4246 return NS_ERROR_FAILURE
;
4250 nsGlobalWindow::DispatchCustomEvent(const char *aEventName
)
4252 PRBool defaultActionEnabled
= PR_TRUE
;
4253 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
4254 nsContentUtils::DispatchTrustedEvent(doc
,
4255 static_cast<nsIScriptGlobalObject
*>(this),
4256 NS_ConvertASCIItoUTF16(aEventName
),
4257 PR_TRUE
, PR_TRUE
, &defaultActionEnabled
);
4259 return defaultActionEnabled
;
4262 static already_AddRefed
<nsIDocShellTreeItem
>
4263 GetCallerDocShellTreeItem()
4265 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
4266 nsIDocShellTreeItem
*callerItem
= nsnull
;
4269 nsCOMPtr
<nsIWebNavigation
> callerWebNav
=
4270 do_GetInterface(nsJSUtils::GetDynamicScriptGlobal(cx
));
4273 CallQueryInterface(callerWebNav
, &callerItem
);
4281 nsGlobalWindow::WindowExists(const nsAString
& aName
,
4282 PRBool aLookForCallerOnJSStack
)
4284 NS_PRECONDITION(IsOuterWindow(), "Must be outer window");
4285 NS_PRECONDITION(mDocShell
, "Must have docshell");
4287 nsCOMPtr
<nsIDocShellTreeItem
> caller
;
4288 if (aLookForCallerOnJSStack
) {
4289 caller
= GetCallerDocShellTreeItem();
4292 nsCOMPtr
<nsIDocShellTreeItem
> docShell
= do_QueryInterface(mDocShell
);
4293 NS_ASSERTION(docShell
,
4294 "Docshell doesn't implement nsIDocShellTreeItem?");
4300 nsCOMPtr
<nsIDocShellTreeItem
> namedItem
;
4301 docShell
->FindItemWithName(PromiseFlatString(aName
).get(), nsnull
, caller
,
4302 getter_AddRefs(namedItem
));
4303 return namedItem
!= nsnull
;
4306 already_AddRefed
<nsIWidget
>
4307 nsGlobalWindow::GetMainWidget()
4309 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4310 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4312 nsIWidget
*widget
= nsnull
;
4314 if (treeOwnerAsWin
) {
4315 treeOwnerAsWin
->GetMainWidget(&widget
);
4322 nsGlobalWindow::GetNearestWidget()
4324 nsIDocShell
* docShell
= GetDocShell();
4325 NS_ENSURE_TRUE(docShell
, nsnull
);
4326 nsCOMPtr
<nsIPresShell
> presShell
;
4327 docShell
->GetPresShell(getter_AddRefs(presShell
));
4328 NS_ENSURE_TRUE(presShell
, nsnull
);
4329 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
4330 NS_ENSURE_TRUE(rootFrame
, nsnull
);
4331 return rootFrame
->GetView()->GetNearestWidget(nsnull
);
4335 nsGlobalWindow::SetFullScreen(PRBool aFullScreen
)
4337 FORWARD_TO_OUTER(SetFullScreen
, (aFullScreen
), NS_ERROR_NOT_INITIALIZED
);
4339 NS_ENSURE_TRUE(mDocShell
, NS_ERROR_FAILURE
);
4341 PRBool rootWinFullScreen
;
4342 GetFullScreen(&rootWinFullScreen
);
4343 // Only chrome can change our fullScreen mode.
4344 if (aFullScreen
== rootWinFullScreen
||
4345 !nsContentUtils::IsCallerTrustedForWrite()) {
4349 // SetFullScreen needs to be called on the root window, so get that
4350 // via the DocShell tree, and if we are not already the root,
4351 // call SetFullScreen on that window instead.
4352 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryInterface(mDocShell
);
4353 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
4354 treeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
4355 nsCOMPtr
<nsIDOMWindowInternal
> window
= do_GetInterface(rootItem
);
4357 return NS_ERROR_FAILURE
;
4358 if (rootItem
!= treeItem
)
4359 return window
->SetFullScreen(aFullScreen
);
4361 // make sure we don't try to set full screen on a non-chrome window,
4362 // which might happen in embedding world
4364 treeItem
->GetItemType(&itemType
);
4365 if (itemType
!= nsIDocShellTreeItem::typeChrome
)
4366 return NS_ERROR_FAILURE
;
4368 // If we are already in full screen mode, just return.
4369 if (mFullScreen
== aFullScreen
)
4372 // dispatch a "fullscreen" DOM event so that XUL apps can
4373 // respond visually if we are kicked into full screen mode
4374 if (!DispatchCustomEvent("fullscreen")) {
4378 // Prevent chrome documents which are still loading from resizing
4379 // the window after we set fullscreen mode.
4380 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4381 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4382 nsCOMPtr
<nsIXULWindow
> xulWin(do_GetInterface(treeOwnerAsWin
));
4383 if (aFullScreen
&& xulWin
) {
4384 xulWin
->SetIntrinsicallySized(PR_FALSE
);
4387 // Set this before so if widget sends an event indicating its
4388 // gone full screen, the state trap above works.
4389 mFullScreen
= aFullScreen
;
4391 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
4393 widget
->MakeFullScreen(aFullScreen
);
4399 nsGlobalWindow::GetFullScreen(PRBool
* aFullScreen
)
4401 FORWARD_TO_OUTER(GetFullScreen
, (aFullScreen
), NS_ERROR_NOT_INITIALIZED
);
4403 // Get the fullscreen value of the root window, to always have the value
4404 // accurate, even when called from content.
4405 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryInterface(mDocShell
);
4407 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
4408 treeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
4409 if (rootItem
!= treeItem
) {
4410 nsCOMPtr
<nsIDOMWindowInternal
> window
= do_GetInterface(rootItem
);
4412 return window
->GetFullScreen(aFullScreen
);
4416 // We are the root window, or something went wrong. Return our internal value.
4417 *aFullScreen
= mFullScreen
;
4422 nsGlobalWindow::DOMWindowDumpEnabled()
4424 #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
4425 // In optimized builds we check a pref that controls if we should
4426 // enable output from dump() or not, in debug builds it's always
4428 return gDOMWindowDumpEnabled
;
4435 nsGlobalWindow::Dump(const nsAString
& aStr
)
4437 if (!DOMWindowDumpEnabled()) {
4441 char *cstr
= ToNewUTF8String(aStr
);
4443 #if defined(XP_MAC) || defined(XP_MACOSX)
4444 // have to convert \r to \n so that printing to the console works
4445 char *c
= cstr
, *cEnd
= cstr
+ strlen(cstr
);
4454 FILE *fp
= gDumpFile
? gDumpFile
: stdout
;
4457 nsMemory::Free(cstr
);
4464 nsGlobalWindow::EnsureReflowFlushAndPaint()
4466 NS_ASSERTION(IsOuterWindow(), "EnsureReflowFlushAndPaint() must be called on"
4467 "the outer window");
4468 NS_ASSERTION(mDocShell
, "EnsureReflowFlushAndPaint() called with no "
4474 nsCOMPtr
<nsIPresShell
> presShell
;
4475 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
4480 // Flush pending reflows.
4482 mDoc
->FlushPendingNotifications(Flush_Layout
);
4485 // Unsuppress painting.
4486 presShell
->UnsuppressPainting();
4490 nsGlobalWindow::GetTextZoom(float *aZoom
)
4492 FORWARD_TO_OUTER(GetTextZoom
, (aZoom
), NS_ERROR_NOT_INITIALIZED
);
4495 nsCOMPtr
<nsIContentViewer
> contentViewer
;
4496 mDocShell
->GetContentViewer(getter_AddRefs(contentViewer
));
4497 nsCOMPtr
<nsIMarkupDocumentViewer
> markupViewer(do_QueryInterface(contentViewer
));
4500 return markupViewer
->GetTextZoom(aZoom
);
4503 return NS_ERROR_FAILURE
;
4507 nsGlobalWindow::SetTextZoom(float aZoom
)
4509 FORWARD_TO_OUTER(SetTextZoom
, (aZoom
), NS_ERROR_NOT_INITIALIZED
);
4512 nsCOMPtr
<nsIContentViewer
> contentViewer
;
4513 mDocShell
->GetContentViewer(getter_AddRefs(contentViewer
));
4514 nsCOMPtr
<nsIMarkupDocumentViewer
> markupViewer(do_QueryInterface(contentViewer
));
4517 return markupViewer
->SetTextZoom(aZoom
);
4519 return NS_ERROR_FAILURE
;
4524 nsGlobalWindow::MakeScriptDialogTitle(nsAString
&aOutTitle
)
4526 aOutTitle
.Truncate();
4528 // Try to get a host from the running principal -- this will do the
4529 // right thing for javascript: and data: documents.
4531 nsresult rv
= NS_OK
;
4532 NS_ASSERTION(nsContentUtils::GetSecurityManager(),
4533 "Global Window has no security manager!");
4534 if (nsContentUtils::GetSecurityManager()) {
4535 nsCOMPtr
<nsIPrincipal
> principal
;
4536 rv
= nsContentUtils::GetSecurityManager()->
4537 GetSubjectPrincipal(getter_AddRefs(principal
));
4539 if (NS_SUCCEEDED(rv
) && principal
) {
4540 nsCOMPtr
<nsIURI
> uri
;
4541 rv
= principal
->GetURI(getter_AddRefs(uri
));
4543 if (NS_SUCCEEDED(rv
) && uri
) {
4544 // remove user:pass for privacy and spoof prevention
4546 nsCOMPtr
<nsIURIFixup
> fixup(do_GetService(NS_URIFIXUP_CONTRACTID
));
4548 nsCOMPtr
<nsIURI
> fixedURI
;
4549 rv
= fixup
->CreateExposableURI(uri
, getter_AddRefs(fixedURI
));
4550 if (NS_SUCCEEDED(rv
) && fixedURI
) {
4552 fixedURI
->GetHost(host
);
4554 if (!host
.IsEmpty()) {
4555 // if this URI has a host we'll show it. For other
4556 // schemes (e.g. file:) we fall back to the localized
4559 nsCAutoString prepath
;
4560 fixedURI
->GetPrePath(prepath
);
4562 NS_ConvertUTF8toUTF16
ucsPrePath(prepath
);
4563 const PRUnichar
*formatStrings
[] = { ucsPrePath
.get() };
4564 nsXPIDLString tempString
;
4565 nsContentUtils::FormatLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
4567 formatStrings
, NS_ARRAY_LENGTH(formatStrings
),
4569 aOutTitle
= tempString
;
4575 else { // failed to get subject principal
4576 NS_WARNING("No script principal? Who is calling alert/confirm/prompt?!");
4580 if (aOutTitle
.IsEmpty()) {
4581 // We didn't find a host so use the generic heading
4582 nsXPIDLString tempString
;
4583 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
4584 "ScriptDlgGenericHeading",
4586 aOutTitle
= tempString
;
4590 if (aOutTitle
.IsEmpty()) {
4591 NS_WARNING("could not get ScriptDlgGenericHeading string from string bundle");
4592 aOutTitle
.AssignLiteral("[Script]");
4598 nsGlobalWindow::CanMoveResizeWindows()
4600 if (!CanSetProperty("dom.disable_window_move_resize"))
4603 if (gMouseDown
&& !gDragServiceDisabled
) {
4604 nsCOMPtr
<nsIDragService
> ds
=
4605 do_GetService("@mozilla.org/widget/dragservice;1");
4607 gDragServiceDisabled
= PR_TRUE
;
4615 nsGlobalWindow::Alert(const nsAString
& aString
)
4617 FORWARD_TO_OUTER(Alert
, (aString
), NS_ERROR_NOT_INITIALIZED
);
4619 if (AreDialogsBlocked())
4620 return NS_ERROR_NOT_AVAILABLE
;
4622 // We have to capture this now so as not to get confused with the
4623 // popup state we push next
4624 PRBool shouldEnableDisableDialog
= DialogOpenAttempted();
4626 // Reset popup state while opening a modal dialog, and firing events
4627 // about the dialog, to prevent the current state from being active
4628 // the whole time a modal dialog is open.
4629 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
4631 // Special handling for alert(null) in JS for backwards
4634 NS_NAMED_LITERAL_STRING(null_str
, "null");
4636 const nsAString
*str
= DOMStringIsNull(aString
) ? &null_str
: &aString
;
4638 // Before bringing up the window, unsuppress painting and flush
4640 EnsureReflowFlushAndPaint();
4643 MakeScriptDialogTitle(title
);
4645 // Remove non-terminating null characters from the
4646 // string. See bug #310037.
4648 nsContentUtils::StripNullChars(*str
, final
);
4650 // Check if we're being called at a point where we can't use tab-modal
4651 // prompts, because something doesn't want reentrancy.
4652 PRBool allowTabModal
= GetIsTabModalPromptAllowed();
4655 nsCOMPtr
<nsIPromptFactory
> promptFac
=
4656 do_GetService("@mozilla.org/prompter;1", &rv
);
4657 NS_ENSURE_SUCCESS(rv
, rv
);
4659 nsCOMPtr
<nsIPrompt
> prompt
;
4660 rv
= promptFac
->GetPrompt(this, NS_GET_IID(nsIPrompt
),
4661 reinterpret_cast<void**>(&prompt
));
4662 NS_ENSURE_SUCCESS(rv
, rv
);
4664 nsCOMPtr
<nsIWritablePropertyBag2
> promptBag
= do_QueryInterface(prompt
);
4666 promptBag
->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), allowTabModal
);
4668 if (shouldEnableDisableDialog
) {
4669 PRBool disallowDialog
= PR_FALSE
;
4670 nsXPIDLString label
;
4671 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
4672 "ScriptDialogLabel", label
);
4674 rv
= prompt
->AlertCheck(title
.get(), final
.get(), label
.get(),
4677 PreventFurtherDialogs();
4679 rv
= prompt
->Alert(title
.get(), final
.get());
4686 nsGlobalWindow::Confirm(const nsAString
& aString
, PRBool
* aReturn
)
4688 FORWARD_TO_OUTER(Confirm
, (aString
, aReturn
), NS_ERROR_NOT_INITIALIZED
);
4690 if (AreDialogsBlocked())
4691 return NS_ERROR_NOT_AVAILABLE
;
4693 // We have to capture this now so as not to get confused with the popup state
4695 PRBool shouldEnableDisableDialog
= DialogOpenAttempted();
4697 // Reset popup state while opening a modal dialog, and firing events
4698 // about the dialog, to prevent the current state from being active
4699 // the whole time a modal dialog is open.
4700 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
4702 *aReturn
= PR_FALSE
;
4704 // Before bringing up the window, unsuppress painting and flush
4706 EnsureReflowFlushAndPaint();
4709 MakeScriptDialogTitle(title
);
4711 // Remove non-terminating null characters from the
4712 // string. See bug #310037.
4714 nsContentUtils::StripNullChars(aString
, final
);
4716 // Check if we're being called at a point where we can't use tab-modal
4717 // prompts, because something doesn't want reentrancy.
4718 PRBool allowTabModal
= GetIsTabModalPromptAllowed();
4721 nsCOMPtr
<nsIPromptFactory
> promptFac
=
4722 do_GetService("@mozilla.org/prompter;1", &rv
);
4723 NS_ENSURE_SUCCESS(rv
, rv
);
4725 nsCOMPtr
<nsIPrompt
> prompt
;
4726 rv
= promptFac
->GetPrompt(this, NS_GET_IID(nsIPrompt
),
4727 reinterpret_cast<void**>(&prompt
));
4728 NS_ENSURE_SUCCESS(rv
, rv
);
4730 nsCOMPtr
<nsIWritablePropertyBag2
> promptBag
= do_QueryInterface(prompt
);
4732 promptBag
->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), allowTabModal
);
4734 if (shouldEnableDisableDialog
) {
4735 PRBool disallowDialog
= PR_FALSE
;
4736 nsXPIDLString label
;
4737 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
4738 "ScriptDialogLabel", label
);
4740 rv
= prompt
->ConfirmCheck(title
.get(), final
.get(), label
.get(),
4741 &disallowDialog
, aReturn
);
4743 PreventFurtherDialogs();
4745 rv
= prompt
->Confirm(title
.get(), final
.get(), aReturn
);
4752 nsGlobalWindow::Prompt(const nsAString
& aMessage
, const nsAString
& aInitial
,
4755 FORWARD_TO_OUTER(Prompt
, (aMessage
, aInitial
, aReturn
),
4756 NS_ERROR_NOT_INITIALIZED
);
4758 SetDOMStringToNull(aReturn
);
4760 if (AreDialogsBlocked())
4761 return NS_ERROR_NOT_AVAILABLE
;
4763 // We have to capture this now so as not to get confused with the popup state
4765 PRBool shouldEnableDisableDialog
= DialogOpenAttempted();
4767 // Reset popup state while opening a modal dialog, and firing events
4768 // about the dialog, to prevent the current state from being active
4769 // the whole time a modal dialog is open.
4770 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
4772 // Before bringing up the window, unsuppress painting and flush
4774 EnsureReflowFlushAndPaint();
4777 MakeScriptDialogTitle(title
);
4779 // Remove non-terminating null characters from the
4780 // string. See bug #310037.
4781 nsAutoString fixedMessage
, fixedInitial
;
4782 nsContentUtils::StripNullChars(aMessage
, fixedMessage
);
4783 nsContentUtils::StripNullChars(aInitial
, fixedInitial
);
4785 // Check if we're being called at a point where we can't use tab-modal
4786 // prompts, because something doesn't want reentrancy.
4787 PRBool allowTabModal
= GetIsTabModalPromptAllowed();
4790 nsCOMPtr
<nsIPromptFactory
> promptFac
=
4791 do_GetService("@mozilla.org/prompter;1", &rv
);
4792 NS_ENSURE_SUCCESS(rv
, rv
);
4794 nsCOMPtr
<nsIPrompt
> prompt
;
4795 rv
= promptFac
->GetPrompt(this, NS_GET_IID(nsIPrompt
),
4796 reinterpret_cast<void**>(&prompt
));
4797 NS_ENSURE_SUCCESS(rv
, rv
);
4799 nsCOMPtr
<nsIWritablePropertyBag2
> promptBag
= do_QueryInterface(prompt
);
4801 promptBag
->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), allowTabModal
);
4803 // Pass in the default value, if any.
4804 PRUnichar
*inoutValue
= ToNewUnicode(fixedInitial
);
4805 PRBool disallowDialog
= PR_FALSE
;
4807 nsXPIDLString label
;
4808 if (shouldEnableDisableDialog
) {
4809 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
4810 "ScriptDialogLabel", label
);
4814 rv
= prompt
->Prompt(title
.get(), fixedMessage
.get(),
4815 &inoutValue
, label
.get(), &disallowDialog
, &ok
);
4817 if (disallowDialog
) {
4818 PreventFurtherDialogs();
4821 NS_ENSURE_SUCCESS(rv
, rv
);
4823 nsAdoptingString
outValue(inoutValue
);
4825 if (ok
&& outValue
) {
4826 aReturn
.Assign(outValue
);
4833 nsGlobalWindow::Focus()
4835 FORWARD_TO_OUTER(Focus
, (), NS_ERROR_NOT_INITIALIZED
);
4837 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
4841 nsCOMPtr
<nsIBaseWindow
> baseWin
= do_QueryInterface(mDocShell
);
4843 PRBool isVisible
= PR_FALSE
;
4845 baseWin
->GetVisibility(&isVisible
);
4849 // A hidden tab is being focused, ignore this call.
4853 nsIDOMWindowInternal
*caller
=
4854 static_cast<nsIDOMWindowInternal
*>(nsContentUtils::GetWindowFromCaller());
4855 nsCOMPtr
<nsIDOMWindowInternal
> opener
;
4856 GetOpener(getter_AddRefs(opener
));
4858 // Enforce dom.disable_window_flip (for non-chrome), but still allow the
4859 // window which opened us to raise us at times when popups are allowed
4860 // (bugs 355482 and 369306).
4861 PRBool canFocus
= CanSetProperty("dom.disable_window_flip") ||
4862 (opener
== caller
&&
4863 RevisePopupAbuseLevel(gPopupControlState
) < openAbused
);
4865 nsCOMPtr
<nsIDOMWindow
> activeWindow
;
4866 fm
->GetActiveWindow(getter_AddRefs(activeWindow
));
4868 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryInterface(mDocShell
);
4869 NS_ASSERTION(treeItem
, "What happened?");
4870 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
4871 treeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
4872 nsCOMPtr
<nsIDOMWindow
> rootWin
= do_GetInterface(rootItem
);
4873 PRBool isActive
= (rootWin
== activeWindow
);
4875 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4876 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4877 if (treeOwnerAsWin
&& (canFocus
|| isActive
)) {
4878 PRBool isEnabled
= PR_TRUE
;
4879 if (NS_SUCCEEDED(treeOwnerAsWin
->GetEnabled(&isEnabled
)) && !isEnabled
) {
4880 NS_WARNING( "Should not try to set the focus on a disabled window" );
4884 // XXXndeakin not sure what this is for or if it should go somewhere else
4885 nsCOMPtr
<nsIEmbeddingSiteWindow
> embeddingWin(do_GetInterface(treeOwnerAsWin
));
4887 embeddingWin
->SetFocus();
4893 nsCOMPtr
<nsIPresShell
> presShell
;
4894 // Don't look for a presshell if we're a root chrome window that's got
4895 // about:blank loaded. We don't want to focus our widget in that case.
4896 // XXXbz should we really be checking for IsInitialDocument() instead?
4897 PRBool lookForPresShell
= PR_TRUE
;
4898 PRInt32 itemType
= nsIDocShellTreeItem::typeContent
;
4899 treeItem
->GetItemType(&itemType
);
4900 if (itemType
== nsIDocShellTreeItem::typeChrome
&&
4901 GetPrivateRoot() == static_cast<nsIDOMWindowInternal
*>(this) &&
4903 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
4904 NS_ASSERTION(doc
, "Bogus doc?");
4905 nsIURI
* ourURI
= doc
->GetDocumentURI();
4907 lookForPresShell
= !IsAboutBlank(ourURI
);
4911 if (lookForPresShell
) {
4912 mDocShell
->GetEldestPresShell(getter_AddRefs(presShell
));
4915 nsCOMPtr
<nsIDocShellTreeItem
> parentDsti
;
4916 treeItem
->GetParent(getter_AddRefs(parentDsti
));
4918 // set the parent's current focus to the frame containing this window.
4919 nsCOMPtr
<nsIDOMWindow
> parent(do_GetInterface(parentDsti
));
4921 nsCOMPtr
<nsIDOMDocument
> parentdomdoc
;
4922 parent
->GetDocument(getter_AddRefs(parentdomdoc
));
4924 nsCOMPtr
<nsIDocument
> parentdoc
= do_QueryInterface(parentdomdoc
);
4928 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(mDocument
);
4929 nsIContent
* frame
= parentdoc
->FindContentForSubDocument(doc
);
4930 nsCOMPtr
<nsIDOMElement
> frameElement
= do_QueryInterface(frame
);
4932 PRUint32 flags
= nsIFocusManager::FLAG_NOSCROLL
;
4934 flags
|= nsIFocusManager::FLAG_RAISE
;
4935 return fm
->SetFocus(frameElement
, flags
);
4938 else if (canFocus
) {
4939 // if there is no parent, this must be a toplevel window, so raise the
4940 // window if canFocus is true
4941 return fm
->SetActiveWindow(this);
4948 nsGlobalWindow::Blur()
4950 FORWARD_TO_OUTER(Blur
, (), NS_ERROR_NOT_INITIALIZED
);
4952 // If dom.disable_window_flip == true, then content should not be allowed
4953 // to call this function (this would allow popunders, bug 369306)
4954 if (!CanSetProperty("dom.disable_window_flip")) {
4958 // If embedding apps don't implement nsIEmbeddingSiteWindow2, we
4959 // shouldn't throw exceptions to web content.
4960 nsresult rv
= NS_OK
;
4962 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
4963 GetTreeOwner(getter_AddRefs(treeOwner
));
4964 nsCOMPtr
<nsIEmbeddingSiteWindow2
> siteWindow(do_GetInterface(treeOwner
));
4966 // This method call may cause mDocShell to become nsnull.
4967 rv
= siteWindow
->Blur();
4969 // if the root is focused, clear the focus
4970 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
4971 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(mDocument
);
4972 if (fm
&& mDocument
) {
4973 nsCOMPtr
<nsIDOMElement
> element
;
4974 fm
->GetFocusedElementForWindow(this, PR_FALSE
, nsnull
, getter_AddRefs(element
));
4975 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(element
);
4976 if (content
== doc
->GetRootElement())
4977 fm
->ClearFocus(this);
4985 nsGlobalWindow::Back()
4987 FORWARD_TO_OUTER(Back
, (), NS_ERROR_NOT_INITIALIZED
);
4989 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
4990 NS_ENSURE_TRUE(webNav
, NS_ERROR_FAILURE
);
4992 return webNav
->GoBack();
4996 nsGlobalWindow::Forward()
4998 FORWARD_TO_OUTER(Forward
, (), NS_ERROR_NOT_INITIALIZED
);
5000 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
5001 NS_ENSURE_TRUE(webNav
, NS_ERROR_FAILURE
);
5003 return webNav
->GoForward();
5007 nsGlobalWindow::Home()
5009 FORWARD_TO_OUTER(Home
, (), NS_ERROR_NOT_INITIALIZED
);
5014 nsAdoptingString homeURL
=
5015 nsContentUtils::GetLocalizedStringPref(PREF_BROWSER_STARTUP_HOMEPAGE
);
5017 if (homeURL
.IsEmpty()) {
5018 // if all else fails, use this
5020 printf("all else failed. using %s as the home page\n", DEFAULT_HOME_PAGE
);
5022 CopyASCIItoUTF16(DEFAULT_HOME_PAGE
, homeURL
);
5027 // Firefox lets the user specify multiple home pages to open in
5028 // individual tabs by separating them with '|'. Since we don't
5029 // have the machinery in place to easily open new tabs from here,
5030 // simply truncate the homeURL at the first '|' character to
5031 // prevent any possibilities of leaking the users list of home
5032 // pages to the first home page.
5034 // Once bug https://bugzilla.mozilla.org/show_bug.cgi?id=221445 is
5035 // fixed we can revisit this.
5036 PRInt32 firstPipe
= homeURL
.FindChar('|');
5038 if (firstPipe
> 0) {
5039 homeURL
.Truncate(firstPipe
);
5045 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
5046 NS_ENSURE_TRUE(webNav
, NS_ERROR_FAILURE
);
5047 rv
= webNav
->LoadURI(homeURL
.get(),
5048 nsIWebNavigation::LOAD_FLAGS_NONE
,
5052 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
5057 nsGlobalWindow::Stop()
5059 FORWARD_TO_OUTER(Stop
, (), NS_ERROR_NOT_INITIALIZED
);
5061 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
5065 return webNav
->Stop(nsIWebNavigation::STOP_ALL
);
5069 nsGlobalWindow::Print()
5072 FORWARD_TO_OUTER(Print
, (), NS_ERROR_NOT_INITIALIZED
);
5074 if (AreDialogsBlocked() || !ConfirmDialogAllowed())
5075 return NS_ERROR_NOT_AVAILABLE
;
5077 nsCOMPtr
<nsIWebBrowserPrint
> webBrowserPrint
;
5078 if (NS_SUCCEEDED(GetInterface(NS_GET_IID(nsIWebBrowserPrint
),
5079 getter_AddRefs(webBrowserPrint
)))) {
5081 nsCOMPtr
<nsIPrintSettingsService
> printSettingsService
=
5082 do_GetService("@mozilla.org/gfx/printsettings-service;1");
5084 nsCOMPtr
<nsIPrintSettings
> printSettings
;
5085 if (printSettingsService
) {
5086 PRBool printSettingsAreGlobal
=
5087 nsContentUtils::GetBoolPref("print.use_global_printsettings", PR_FALSE
);
5089 if (printSettingsAreGlobal
) {
5090 printSettingsService
->GetGlobalPrintSettings(getter_AddRefs(printSettings
));
5092 nsXPIDLString printerName
;
5093 printSettings
->GetPrinterName(getter_Copies(printerName
));
5094 if (printerName
.IsEmpty()) {
5095 printSettingsService
->GetDefaultPrinterName(getter_Copies(printerName
));
5096 printSettings
->SetPrinterName(printerName
);
5098 printSettingsService
->InitPrintSettingsFromPrinter(printerName
, printSettings
);
5099 printSettingsService
->InitPrintSettingsFromPrefs(printSettings
,
5101 nsIPrintSettings::kInitSaveAll
);
5103 printSettingsService
->GetNewPrintSettings(getter_AddRefs(printSettings
));
5107 webBrowserPrint
->Print(printSettings
, nsnull
);
5108 LeaveModalState(nsnull
);
5110 PRBool savePrintSettings
=
5111 nsContentUtils::GetBoolPref("print.save_print_settings", PR_FALSE
);
5112 if (printSettingsAreGlobal
&& savePrintSettings
) {
5113 printSettingsService
->
5114 SavePrintSettingsToPrefs(printSettings
,
5116 nsIPrintSettings::kInitSaveAll
);
5117 printSettingsService
->
5118 SavePrintSettingsToPrefs(printSettings
,
5120 nsIPrintSettings::kInitSavePrinterName
);
5123 webBrowserPrint
->GetGlobalPrintSettings(getter_AddRefs(printSettings
));
5124 webBrowserPrint
->Print(printSettings
, nsnull
);
5127 #endif //NS_PRINTING
5133 nsGlobalWindow::MoveTo(PRInt32 aXPos
, PRInt32 aYPos
)
5135 FORWARD_TO_OUTER(MoveTo
, (aXPos
, aYPos
), NS_ERROR_NOT_INITIALIZED
);
5138 * If caller is not chrome and the user has not explicitly exempted the site,
5139 * prevent window.moveTo() by exiting early
5142 if (!CanMoveResizeWindows() || IsFrame()) {
5146 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
5147 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
5148 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
5150 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&aXPos
, &aYPos
),
5153 // mild abuse of a "size" object so we don't need more helper functions
5154 nsIntSize
devPos(CSSToDevIntPixels(nsIntSize(aXPos
, aYPos
)));
5156 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(devPos
.width
, devPos
.height
),
5163 nsGlobalWindow::MoveBy(PRInt32 aXDif
, PRInt32 aYDif
)
5165 FORWARD_TO_OUTER(MoveBy
, (aXDif
, aYDif
), NS_ERROR_NOT_INITIALIZED
);
5168 * If caller is not chrome and the user has not explicitly exempted the site,
5169 * prevent window.moveBy() by exiting early
5172 if (!CanMoveResizeWindows() || IsFrame()) {
5176 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
5177 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
5178 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
5180 // To do this correctly we have to convert what we get from GetPosition
5181 // into CSS pixels, add the arguments, do the security check, and
5182 // then convert back to device pixels for the call to SetPosition.
5185 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
), NS_ERROR_FAILURE
);
5187 // mild abuse of a "size" object so we don't need more helper functions
5188 nsIntSize
cssPos(DevToCSSIntPixels(nsIntSize(x
, y
)));
5190 cssPos
.width
+= aXDif
;
5191 cssPos
.height
+= aYDif
;
5193 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&cssPos
.width
,
5197 nsIntSize
newDevPos(CSSToDevIntPixels(cssPos
));
5199 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(newDevPos
.width
,
5207 nsGlobalWindow::ResizeTo(PRInt32 aWidth
, PRInt32 aHeight
)
5209 FORWARD_TO_OUTER(ResizeTo
, (aWidth
, aHeight
), NS_ERROR_NOT_INITIALIZED
);
5212 * If caller is not chrome and the user has not explicitly exempted the site,
5213 * prevent window.resizeTo() by exiting early
5216 if (!CanMoveResizeWindows() || IsFrame()) {
5220 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
5221 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
5222 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
5224 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&aWidth
, &aHeight
),
5227 nsIntSize
devSz(CSSToDevIntPixels(nsIntSize(aWidth
, aHeight
)));
5229 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetSize(devSz
.width
, devSz
.height
, PR_TRUE
),
5236 nsGlobalWindow::ResizeBy(PRInt32 aWidthDif
, PRInt32 aHeightDif
)
5238 FORWARD_TO_OUTER(ResizeBy
, (aWidthDif
, aHeightDif
), NS_ERROR_NOT_INITIALIZED
);
5241 * If caller is not chrome and the user has not explicitly exempted the site,
5242 * prevent window.resizeBy() by exiting early
5245 if (!CanMoveResizeWindows() || IsFrame()) {
5249 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
5250 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
5251 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
5253 PRInt32 width
, height
;
5254 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetSize(&width
, &height
), NS_ERROR_FAILURE
);
5256 // To do this correctly we have to convert what we got from GetSize
5257 // into CSS pixels, add the arguments, do the security check, and
5258 // then convert back to device pixels for the call to SetSize.
5260 nsIntSize
cssSize(DevToCSSIntPixels(nsIntSize(width
, height
)));
5262 cssSize
.width
+= aWidthDif
;
5263 cssSize
.height
+= aHeightDif
;
5265 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&cssSize
.width
,
5269 nsIntSize
newDevSize(CSSToDevIntPixels(cssSize
));
5271 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetSize(newDevSize
.width
,
5280 nsGlobalWindow::SizeToContent()
5282 FORWARD_TO_OUTER(SizeToContent
, (), NS_ERROR_NOT_INITIALIZED
);
5289 * If caller is not chrome and the user has not explicitly exempted the site,
5290 * prevent window.sizeToContent() by exiting early
5293 if (!CanMoveResizeWindows() || IsFrame()) {
5297 // The content viewer does a check to make sure that it's a content
5298 // viewer for a toplevel docshell.
5300 nsCOMPtr
<nsIContentViewer
> cv
;
5301 mDocShell
->GetContentViewer(getter_AddRefs(cv
));
5302 nsCOMPtr
<nsIMarkupDocumentViewer
> markupViewer(do_QueryInterface(cv
));
5303 NS_ENSURE_TRUE(markupViewer
, NS_ERROR_FAILURE
);
5304 NS_ENSURE_SUCCESS(markupViewer
->SizeToContent(), NS_ERROR_FAILURE
);
5310 nsGlobalWindow::GetWindowRoot(nsIDOMEventTarget
**aWindowRoot
)
5312 nsCOMPtr
<nsPIWindowRoot
> root
= GetTopWindowRoot();
5313 return CallQueryInterface(root
, aWindowRoot
);
5316 already_AddRefed
<nsPIWindowRoot
>
5317 nsGlobalWindow::GetTopWindowRoot()
5319 nsIDOMWindowInternal
*rootWindow
= GetPrivateRoot();
5320 nsCOMPtr
<nsPIDOMWindow
> piWin(do_QueryInterface(rootWindow
));
5324 nsCOMPtr
<nsPIWindowRoot
> window
= do_QueryInterface(piWin
->GetChromeEventHandler());
5325 return window
.forget();
5329 nsGlobalWindow::Scroll(PRInt32 aXScroll
, PRInt32 aYScroll
)
5331 return ScrollTo(aXScroll
, aYScroll
);
5335 nsGlobalWindow::ScrollTo(PRInt32 aXScroll
, PRInt32 aYScroll
)
5337 FlushPendingNotifications(Flush_Layout
);
5338 nsIScrollableFrame
*sf
= GetScrollFrame();
5341 // Here we calculate what the max pixel value is that we can
5342 // scroll to, we do this by dividing maxint with the pixel to
5343 // twips conversion factor, and substracting 4, the 4 comes from
5344 // experimenting with this value, anything less makes the view
5345 // code not scroll correctly, I have no idea why. -- jst
5346 const PRInt32 maxpx
= nsPresContext::AppUnitsToIntCSSPixels(0x7fffffff) - 4;
5348 if (aXScroll
> maxpx
) {
5352 if (aYScroll
> maxpx
) {
5355 sf
->ScrollTo(nsPoint(nsPresContext::CSSPixelsToAppUnits(aXScroll
),
5356 nsPresContext::CSSPixelsToAppUnits(aYScroll
)),
5357 nsIScrollableFrame::INSTANT
);
5364 nsGlobalWindow::ScrollBy(PRInt32 aXScrollDif
, PRInt32 aYScrollDif
)
5366 FlushPendingNotifications(Flush_Layout
);
5367 nsIScrollableFrame
*sf
= GetScrollFrame();
5370 nsPoint scrollPos
= sf
->GetScrollPosition();
5371 // It seems like it would make more sense for ScrollBy to use
5372 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
5373 // Perhaps Web content does too.
5374 return ScrollTo(nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.x
) + aXScrollDif
,
5375 nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.y
) + aYScrollDif
);
5382 nsGlobalWindow::ScrollByLines(PRInt32 numLines
)
5384 FlushPendingNotifications(Flush_Layout
);
5385 nsIScrollableFrame
*sf
= GetScrollFrame();
5387 // It seems like it would make more sense for ScrollByLines to use
5388 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
5389 // Perhaps Web content does too.
5390 sf
->ScrollBy(nsIntPoint(0, numLines
), nsIScrollableFrame::LINES
,
5391 nsIScrollableFrame::INSTANT
);
5398 nsGlobalWindow::ScrollByPages(PRInt32 numPages
)
5400 FlushPendingNotifications(Flush_Layout
);
5401 nsIScrollableFrame
*sf
= GetScrollFrame();
5403 // It seems like it would make more sense for ScrollByPages to use
5404 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
5405 // Perhaps Web content does too.
5406 sf
->ScrollBy(nsIntPoint(0, numPages
), nsIScrollableFrame::PAGES
,
5407 nsIScrollableFrame::INSTANT
);
5414 nsGlobalWindow::ClearTimeout()
5416 return ClearTimeoutOrInterval();
5420 nsGlobalWindow::ClearInterval()
5422 return ClearTimeoutOrInterval();
5426 nsGlobalWindow::SetTimeout(PRInt32
*_retval
)
5428 return SetTimeoutOrInterval(PR_FALSE
, _retval
);
5432 nsGlobalWindow::SetInterval(PRInt32
*_retval
)
5434 return SetTimeoutOrInterval(PR_TRUE
, _retval
);
5438 nsGlobalWindow::SetResizable(PRBool aResizable
)
5446 ReportUseOfDeprecatedMethod(nsGlobalWindow
* aWindow
, const char* aWarning
)
5448 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(aWindow
->GetExtantDocument());
5449 nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES
,
5453 EmptyString(), 0, 0,
5454 nsIScriptError::warningFlag
,
5459 nsGlobalWindow::CaptureEvents(PRInt32 aEventFlags
)
5461 ReportUseOfDeprecatedMethod(this, "UseOfCaptureEventsWarning");
5466 nsGlobalWindow::ReleaseEvents(PRInt32 aEventFlags
)
5468 ReportUseOfDeprecatedMethod(this, "UseOfReleaseEventsWarning");
5473 nsGlobalWindow::RouteEvent(nsIDOMEvent
* aEvt
)
5475 ReportUseOfDeprecatedMethod(this, "UseOfRouteEventWarning");
5480 nsGlobalWindow::EnableExternalCapture()
5482 return NS_ERROR_FAILURE
;
5486 nsGlobalWindow::DisableExternalCapture()
5488 return NS_ERROR_FAILURE
;
5492 PRBool
IsPopupBlocked(nsIDOMDocument
* aDoc
)
5494 nsCOMPtr
<nsIPopupWindowManager
> pm
=
5495 do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID
);
5501 PRBool blocked
= PR_TRUE
;
5502 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(aDoc
));
5505 PRUint32 permission
= nsIPopupWindowManager::ALLOW_POPUP
;
5506 pm
->TestPermission(doc
->GetDocumentURI(), &permission
);
5507 blocked
= (permission
== nsIPopupWindowManager::DENY_POPUP
);
5514 nsGlobalWindow::FirePopupBlockedEvent(nsIDOMDocument
* aDoc
,
5515 nsIDOMWindow
*aRequestingWindow
, nsIURI
*aPopupURI
,
5516 const nsAString
&aPopupWindowName
,
5517 const nsAString
&aPopupWindowFeatures
)
5520 // Fire a "DOMPopupBlocked" event so that the UI can hear about
5522 nsCOMPtr
<nsIDOMDocumentEvent
> docEvent(do_QueryInterface(aDoc
));
5523 nsCOMPtr
<nsIDOMEvent
> event
;
5524 docEvent
->CreateEvent(NS_LITERAL_STRING("PopupBlockedEvents"),
5525 getter_AddRefs(event
));
5527 nsCOMPtr
<nsIDOMPopupBlockedEvent
> pbev(do_QueryInterface(event
));
5528 pbev
->InitPopupBlockedEvent(NS_LITERAL_STRING("DOMPopupBlocked"),
5529 PR_TRUE
, PR_TRUE
, aRequestingWindow
,
5530 aPopupURI
, aPopupWindowName
,
5531 aPopupWindowFeatures
);
5532 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(event
));
5533 privateEvent
->SetTrusted(PR_TRUE
);
5535 nsCOMPtr
<nsIDOMEventTarget
> targ(do_QueryInterface(aDoc
));
5536 PRBool defaultActionEnabled
;
5537 targ
->DispatchEvent(event
, &defaultActionEnabled
);
5542 void FirePopupWindowEvent(nsIDOMDocument
* aDoc
)
5544 // Fire a "PopupWindow" event
5545 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(aDoc
));
5546 nsContentUtils::DispatchTrustedEvent(doc
, aDoc
,
5547 NS_LITERAL_STRING("PopupWindow"),
5553 nsGlobalWindow::CanSetProperty(const char *aPrefName
)
5555 // Chrome can set any property.
5556 if (nsContentUtils::IsCallerTrustedForWrite()) {
5560 // If the pref is set to true, we can not set the property
5562 return !nsContentUtils::GetBoolPref(aPrefName
, PR_TRUE
);
5566 nsGlobalWindow::PopupWhitelisted()
5568 if (!IsPopupBlocked(mDocument
))
5571 nsCOMPtr
<nsIDOMWindow
> parent
;
5573 if (NS_FAILED(GetParent(getter_AddRefs(parent
))) ||
5574 parent
== static_cast<nsIDOMWindow
*>(this))
5579 return static_cast<nsGlobalWindow
*>
5580 (static_cast<nsIDOMWindow
*>
5581 (parent
.get()))->PopupWhitelisted();
5585 * Examine the current document state to see if we're in a way that is
5586 * typically abused by web designers. The window.open code uses this
5587 * routine to determine whether to allow the new window.
5588 * Returns a value from the PopupControlState enum.
5591 nsGlobalWindow::RevisePopupAbuseLevel(PopupControlState aControl
)
5593 FORWARD_TO_OUTER(RevisePopupAbuseLevel
, (aControl
), aControl
);
5595 NS_ASSERTION(mDocShell
, "Must have docshell");
5597 nsCOMPtr
<nsIDocShellTreeItem
> item(do_QueryInterface(mDocShell
));
5599 NS_ASSERTION(item
, "Docshell doesn't implement nsIDocShellTreeItem?");
5601 PRInt32 type
= nsIDocShellTreeItem::typeChrome
;
5602 item
->GetItemType(&type
);
5603 if (type
!= nsIDocShellTreeItem::typeContent
)
5606 PopupControlState abuse
= aControl
;
5608 case openControlled
:
5610 case openOverridden
:
5611 if (PopupWhitelisted())
5612 abuse
= PopupControlState(abuse
- 1);
5613 case openAllowed
: break;
5615 NS_WARNING("Strange PopupControlState!");
5618 // limit the number of simultaneously open popups
5619 if (abuse
== openAbused
|| abuse
== openControlled
) {
5620 PRInt32 popupMax
= nsContentUtils::GetIntPref("dom.popup_maximum", -1);
5621 if (popupMax
>= 0 && gOpenPopupSpamCount
>= popupMax
)
5622 abuse
= openOverridden
;
5628 /* If a window open is blocked, fire the appropriate DOM events.
5629 aBlocked signifies we just blocked a popup.
5630 aWindow signifies we just opened what is probably a popup.
5633 nsGlobalWindow::FireAbuseEvents(PRBool aBlocked
, PRBool aWindow
,
5634 const nsAString
&aPopupURL
,
5635 const nsAString
&aPopupWindowName
,
5636 const nsAString
&aPopupWindowFeatures
)
5638 // fetch the URI of the window requesting the opened window
5640 nsCOMPtr
<nsIDOMWindow
> topWindow
;
5641 GetTop(getter_AddRefs(topWindow
));
5645 nsCOMPtr
<nsIDOMDocument
> topDoc
;
5646 topWindow
->GetDocument(getter_AddRefs(topDoc
));
5648 nsCOMPtr
<nsIURI
> popupURI
;
5650 // build the URI of the would-have-been popup window
5651 // (see nsWindowWatcher::URIfromURL)
5653 // first, fetch the opener's base URI
5655 nsIURI
*baseURL
= 0;
5657 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
5658 nsCOMPtr
<nsIDOMWindow
> contextWindow
;
5661 nsIScriptContext
*currentCX
= nsJSUtils::GetDynamicScriptContext(cx
);
5663 contextWindow
= do_QueryInterface(currentCX
->GetGlobalObject());
5667 contextWindow
= static_cast<nsIDOMWindow
*>(this);
5669 nsCOMPtr
<nsIDOMDocument
> domdoc
;
5670 contextWindow
->GetDocument(getter_AddRefs(domdoc
));
5671 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(domdoc
));
5673 baseURL
= doc
->GetDocBaseURI();
5675 // use the base URI to build what would have been the popup's URI
5676 nsCOMPtr
<nsIIOService
> ios(do_GetService(NS_IOSERVICE_CONTRACTID
));
5678 ios
->NewURI(NS_ConvertUTF16toUTF8(aPopupURL
), 0, baseURL
,
5679 getter_AddRefs(popupURI
));
5681 // fire an event chock full of informative URIs
5683 FirePopupBlockedEvent(topDoc
, this, popupURI
, aPopupWindowName
,
5684 aPopupWindowFeatures
);
5686 FirePopupWindowEvent(topDoc
);
5690 nsGlobalWindow::Open(const nsAString
& aUrl
, const nsAString
& aName
,
5691 const nsAString
& aOptions
, nsIDOMWindow
**_retval
)
5693 return OpenInternal(aUrl
, aName
, aOptions
,
5694 PR_FALSE
, // aDialog
5695 PR_FALSE
, // aContentModal
5696 PR_TRUE
, // aCalledNoScript
5697 PR_FALSE
, // aDoJSFixups
5698 nsnull
, nsnull
, // No args
5699 GetPrincipal(), // aCalleePrincipal
5700 nsnull
, // aJSCallerContext
5705 nsGlobalWindow::OpenJS(const nsAString
& aUrl
, const nsAString
& aName
,
5706 const nsAString
& aOptions
, nsIDOMWindow
**_retval
)
5708 return OpenInternal(aUrl
, aName
, aOptions
,
5709 PR_FALSE
, // aDialog
5710 PR_FALSE
, // aContentModal
5711 PR_FALSE
, // aCalledNoScript
5712 PR_TRUE
, // aDoJSFixups
5713 nsnull
, nsnull
, // No args
5714 GetPrincipal(), // aCalleePrincipal
5715 nsContentUtils::GetCurrentJSContext(), // aJSCallerContext
5719 // like Open, but attaches to the new window any extra parameters past
5720 // [features] as a JS property named "arguments"
5722 nsGlobalWindow::OpenDialog(const nsAString
& aUrl
, const nsAString
& aName
,
5723 const nsAString
& aOptions
,
5724 nsISupports
* aExtraArgument
, nsIDOMWindow
** _retval
)
5726 return OpenInternal(aUrl
, aName
, aOptions
,
5728 PR_FALSE
, // aContentModal
5729 PR_TRUE
, // aCalledNoScript
5730 PR_FALSE
, // aDoJSFixups
5731 nsnull
, aExtraArgument
, // Arguments
5732 GetPrincipal(), // aCalleePrincipal
5733 nsnull
, // aJSCallerContext
5738 nsGlobalWindow::OpenDialog(const nsAString
& aUrl
, const nsAString
& aName
,
5739 const nsAString
& aOptions
, nsIDOMWindow
** _retval
)
5741 if (!nsContentUtils::IsCallerTrustedForWrite()) {
5742 return NS_ERROR_DOM_SECURITY_ERR
;
5745 nsAXPCNativeCallContext
*ncc
= nsnull
;
5746 nsresult rv
= nsContentUtils::XPConnect()->
5747 GetCurrentNativeCallContext(&ncc
);
5748 NS_ENSURE_SUCCESS(rv
, rv
);
5751 return NS_ERROR_NOT_AVAILABLE
;
5753 JSContext
*cx
= nsnull
;
5755 rv
= ncc
->GetJSContext(&cx
);
5756 NS_ENSURE_SUCCESS(rv
, rv
);
5759 jsval
*argv
= nsnull
;
5761 // XXX - need to get this as nsISupports?
5762 ncc
->GetArgc(&argc
);
5763 ncc
->GetArgvPtr(&argv
);
5765 // Strip the url, name and options from the args seen by scripts.
5766 PRUint32 argOffset
= argc
< 3 ? argc
: 3;
5767 nsCOMPtr
<nsIArray
> argvArray
;
5768 rv
= NS_CreateJSArgv(cx
, argc
- argOffset
, argv
+ argOffset
,
5769 getter_AddRefs(argvArray
));
5770 NS_ENSURE_SUCCESS(rv
, rv
);
5772 return OpenInternal(aUrl
, aName
, aOptions
,
5774 PR_FALSE
, // aContentModal
5775 PR_FALSE
, // aCalledNoScript
5776 PR_FALSE
, // aDoJSFixups
5777 argvArray
, nsnull
, // Arguments
5778 GetPrincipal(), // aCalleePrincipal
5779 cx
, // aJSCallerContext
5784 nsGlobalWindow::GetFrames(nsIDOMWindow
** aFrames
)
5786 FORWARD_TO_OUTER(GetFrames
, (aFrames
), NS_ERROR_NOT_INITIALIZED
);
5789 NS_ADDREF(*aFrames
);
5791 FlushPendingNotifications(Flush_ContentAndNotify
);
5797 nsGlobalWindow::CallerInnerWindow()
5799 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
5801 NS_ERROR("Please don't call this method from C++!");
5806 JSObject
*scope
= nsnull
;
5807 JSStackFrame
*fp
= nsnull
;
5808 JS_FrameIterator(cx
, &fp
);
5810 while (fp
->isDummyFrame()) {
5811 if (!JS_FrameIterator(cx
, &fp
))
5816 scope
= &fp
->scopeChain();
5820 scope
= JS_GetScopeChain(cx
);
5822 JSAutoEnterCompartment ac
;
5823 if (!ac
.enter(cx
, scope
))
5826 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
5827 nsContentUtils::XPConnect()->
5828 GetWrappedNativeOfJSObject(cx
, ::JS_GetGlobalForObject(cx
, scope
),
5829 getter_AddRefs(wrapper
));
5833 // The calling window must be holding a reference, so we can just return a
5834 // raw pointer here and let the QI's addref be balanced by the nsCOMPtr
5835 // destructor's release.
5836 nsCOMPtr
<nsPIDOMWindow
> win
= do_QueryWrappedNative(wrapper
);
5838 return GetCurrentInnerWindowInternal();
5839 return static_cast<nsGlobalWindow
*>(win
.get());
5844 * Class used to represent events generated by calls to Window.postMessage,
5845 * which asynchronously creates and dispatches events.
5847 class PostMessageEvent
: public nsRunnable
5852 PostMessageEvent(nsGlobalWindow
* aSource
,
5853 const nsAString
& aCallerOrigin
,
5854 const nsAString
& aMessage
,
5855 nsGlobalWindow
* aTargetWindow
,
5856 nsIURI
* aProvidedOrigin
,
5857 PRBool aTrustedCaller
)
5859 mCallerOrigin(aCallerOrigin
),
5861 mTargetWindow(aTargetWindow
),
5862 mProvidedOrigin(aProvidedOrigin
),
5863 mTrustedCaller(aTrustedCaller
)
5865 MOZ_COUNT_CTOR(PostMessageEvent
);
5870 MOZ_COUNT_DTOR(PostMessageEvent
);
5874 nsRefPtr
<nsGlobalWindow
> mSource
;
5875 nsString mCallerOrigin
;
5877 nsRefPtr
<nsGlobalWindow
> mTargetWindow
;
5878 nsCOMPtr
<nsIURI
> mProvidedOrigin
;
5879 PRBool mTrustedCaller
;
5883 PostMessageEvent::Run()
5885 NS_ABORT_IF_FALSE(mTargetWindow
->IsOuterWindow(),
5886 "should have been passed an outer window!");
5887 NS_ABORT_IF_FALSE(!mSource
|| mSource
->IsOuterWindow(),
5888 "should have been passed an outer window!");
5890 nsRefPtr
<nsGlobalWindow
> targetWindow
;
5891 if (mTargetWindow
->IsClosedOrClosing() ||
5892 !(targetWindow
= mTargetWindow
->GetCurrentInnerWindowInternal()) ||
5893 targetWindow
->IsClosedOrClosing())
5896 NS_ABORT_IF_FALSE(targetWindow
->IsInnerWindow(),
5897 "we ordered an inner window!");
5899 // Ensure that any origin which might have been provided is the origin of this
5900 // window's document. Note that we do this *now* instead of when postMessage
5901 // is called because the target window might have been navigated to a
5902 // different location between then and now. If this check happened when
5903 // postMessage was called, it would be fairly easy for a malicious webpage to
5904 // intercept messages intended for another site by carefully timing navigation
5905 // of the target window so it changed location after postMessage but before
5907 if (mProvidedOrigin
) {
5908 // Get the target's origin either from its principal or, in the case the
5909 // principal doesn't carry a URI (e.g. the system principal), the target's
5911 nsIPrincipal
* targetPrin
= targetWindow
->GetPrincipal();
5914 nsCOMPtr
<nsIURI
> targetURI
;
5915 if (NS_FAILED(targetPrin
->GetURI(getter_AddRefs(targetURI
))))
5918 targetURI
= targetWindow
->mDoc
->GetDocumentURI();
5923 // Note: This is contrary to the spec with respect to file: URLs, which
5924 // the spec groups into a single origin, but given we intentionally
5925 // don't do that in other places it seems better to hold the line for
5926 // now. Long-term, we want HTML5 to address this so that we can
5927 // be compliant while being safer.
5928 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
5930 ssm
->CheckSameOriginURI(mProvidedOrigin
, targetURI
, PR_TRUE
);
5937 nsCOMPtr
<nsIDOMDocumentEvent
> docEvent
=
5938 do_QueryInterface(targetWindow
->mDocument
);
5941 nsCOMPtr
<nsIDOMEvent
> event
;
5942 docEvent
->CreateEvent(NS_LITERAL_STRING("MessageEvent"),
5943 getter_AddRefs(event
));
5947 nsCOMPtr
<nsIDOMMessageEvent
> message
= do_QueryInterface(event
);
5948 nsresult rv
= message
->InitMessageEvent(NS_LITERAL_STRING("message"),
5949 PR_FALSE
/* non-bubbling */,
5950 PR_TRUE
/* cancelable */,
5959 // We can't simply call dispatchEvent on the window because doing so ends
5960 // up flipping the trusted bit on the event, and we don't want that to
5961 // happen because then untrusted content can call postMessage on a chrome
5962 // window if it can get a reference to it.
5964 nsIPresShell
*shell
= targetWindow
->mDoc
->GetShell();
5965 nsRefPtr
<nsPresContext
> presContext
;
5967 presContext
= shell
->GetPresContext();
5969 nsCOMPtr
<nsIPrivateDOMEvent
> privEvent
= do_QueryInterface(message
);
5970 privEvent
->SetTrusted(mTrustedCaller
);
5971 nsEvent
*internalEvent
= privEvent
->GetInternalNSEvent();
5973 nsEventStatus status
= nsEventStatus_eIgnore
;
5974 nsEventDispatcher::Dispatch(static_cast<nsPIDOMWindow
*>(mTargetWindow
),
5983 nsGlobalWindow::PostMessageMoz(const nsAString
& aMessage
, const nsAString
& aOrigin
)
5985 FORWARD_TO_OUTER(PostMessageMoz
, (aMessage
, aOrigin
), NS_ERROR_NOT_INITIALIZED
);
5988 // Window.postMessage is an intentional subversion of the same-origin policy.
5989 // As such, this code must be particularly careful in the information it
5990 // exposes to calling code.
5992 // http://www.whatwg.org/specs/web-apps/current-work/multipage/section-crossDocumentMessages.html
5995 // First, get the caller's window
5996 nsRefPtr
<nsGlobalWindow
> callerInnerWin
= CallerInnerWindow();
5997 if (!callerInnerWin
)
5999 NS_ABORT_IF_FALSE(callerInnerWin
->IsInnerWindow(),
6000 "should have gotten an inner window here");
6002 // Compute the caller's origin either from its principal or, in the case the
6003 // principal doesn't carry a URI (e.g. the system principal), the caller's
6004 // document. We must get this now instead of when the event is created and
6005 // dispatched, because ultimately it is the identity of the calling window
6006 // *now* that determines who sent the message (and not an identity which might
6007 // have changed due to intervening navigations).
6008 nsIPrincipal
* callerPrin
= callerInnerWin
->GetPrincipal();
6012 nsCOMPtr
<nsIURI
> callerOuterURI
;
6013 if (NS_FAILED(callerPrin
->GetURI(getter_AddRefs(callerOuterURI
))))
6016 nsAutoString origin
;
6017 if (callerOuterURI
) {
6018 // if the principal has a URI, use that to generate the origin
6019 nsContentUtils::GetUTFOrigin(callerPrin
, origin
);
6022 // otherwise use the URI of the document to generate origin
6023 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(callerInnerWin
->mDocument
);
6026 callerOuterURI
= doc
->GetDocumentURI();
6027 // if the principal has a URI, use that to generate the origin
6028 nsContentUtils::GetUTFOrigin(callerOuterURI
, origin
);
6031 // Convert the provided origin string into a URI for comparison purposes.
6032 // "*" indicates no specific origin is required.
6033 nsCOMPtr
<nsIURI
> providedOrigin
;
6034 if (!aOrigin
.EqualsASCII("*")) {
6035 if (NS_FAILED(NS_NewURI(getter_AddRefs(providedOrigin
), aOrigin
)))
6036 return NS_ERROR_DOM_SYNTAX_ERR
;
6037 if (NS_FAILED(providedOrigin
->SetUserPass(EmptyCString())) ||
6038 NS_FAILED(providedOrigin
->SetPath(EmptyCString())))
6042 // Create and asynchronously dispatch a runnable which will handle actual DOM
6043 // event creation and dispatch.
6044 nsRefPtr
<PostMessageEvent
> event
=
6045 new PostMessageEvent(nsContentUtils::IsCallerChrome()
6047 : callerInnerWin
->GetOuterWindowInternal(),
6052 nsContentUtils::IsCallerTrustedForWrite());
6053 return NS_DispatchToCurrentThread(event
);
6056 class nsCloseEvent
: public nsRunnable
{
6058 nsRefPtr
<nsGlobalWindow
> mWindow
;
6060 nsCloseEvent(nsGlobalWindow
*aWindow
)
6067 PostCloseEvent(nsGlobalWindow
* aWindow
) {
6068 nsCOMPtr
<nsIRunnable
> ev
= new nsCloseEvent(aWindow
);
6069 nsresult rv
= NS_DispatchToCurrentThread(ev
);
6070 if (NS_SUCCEEDED(rv
))
6071 aWindow
->MaybeForgiveSpamCount();
6077 mWindow
->ReallyCloseWindow();
6084 nsGlobalWindow::CanClose()
6089 // Ask the content viewer whether the toplevel window can close.
6090 // If the content viewer returns false, it is responsible for calling
6091 // Close() as soon as it is possible for the window to close.
6092 // This allows us to not close the window while printing is happening.
6094 nsCOMPtr
<nsIContentViewer
> cv
;
6095 mDocShell
->GetContentViewer(getter_AddRefs(cv
));
6098 nsresult rv
= cv
->PermitUnload(PR_FALSE
, &canClose
);
6099 if (NS_SUCCEEDED(rv
) && !canClose
)
6102 rv
= cv
->RequestWindowClose(&canClose
);
6103 if (NS_SUCCEEDED(rv
) && !canClose
)
6111 nsGlobalWindow::Close()
6113 FORWARD_TO_OUTER(Close
, (), NS_ERROR_NOT_INITIALIZED
);
6115 if (IsFrame() || !mDocShell
|| IsInModalState()) {
6116 // window.close() is called on a frame in a frameset, on a window
6117 // that's already closed, or on a window for which there's
6118 // currently a modal dialog open. Ignore such calls.
6123 if (mHavePendingClose
) {
6124 // We're going to be closed anyway; do nothing since we don't want
6129 if (mBlockScriptedClosingFlag
)
6131 // A script's popup has been blocked and we don't want
6132 // the window to be closed directly after this event,
6133 // so the user can see that there was a blocked popup.
6137 // Don't allow scripts from content to close windows
6138 // that were not opened by script
6139 if (!mHadOriginalOpener
&& !nsContentUtils::IsCallerTrustedForWrite()) {
6141 nsContentUtils::GetBoolPref("dom.allow_scripts_to_close_windows",
6144 // We're blocking the close operation
6145 // report localized error msg in JS console
6146 nsContentUtils::ReportToConsole(
6147 nsContentUtils::eDOM_PROPERTIES
,
6148 "WindowCloseBlockedWarning",
6149 nsnull
, 0, // No params
6151 EmptyString(), 0, 0, // No source, or column/line number
6152 nsIScriptError::warningFlag
,
6153 "DOM Window", mDoc
); // Better name for the category?
6159 if (!mInClose
&& !mIsClosed
&& !CanClose())
6162 // Fire a DOM event notifying listeners that this window is about to
6163 // be closed. The tab UI code may choose to cancel the default
6164 // action for this event, if so, we won't actually close the window
6165 // (since the tab UI code will close the tab in stead). Sure, this
6166 // could be abused by content code, but do we care? I don't think
6169 PRBool wasInClose
= mInClose
;
6172 if (!DispatchCustomEvent("DOMWindowClose")) {
6173 // Someone chose to prevent the default action for this event, if
6174 // so, let's not close this window after all...
6176 mInClose
= wasInClose
;
6180 return FinalClose();
6184 nsGlobalWindow::ForceClose()
6186 if (IsFrame() || !mDocShell
) {
6187 // This may be a frame in a frameset, or a window that's already closed.
6188 // Ignore such calls.
6193 if (mHavePendingClose
) {
6194 // We're going to be closed anyway; do nothing since we don't want
6201 DispatchCustomEvent("DOMWindowClose");
6203 return FinalClose();
6207 nsGlobalWindow::FinalClose()
6210 // Flag that we were closed.
6211 mIsClosed
= PR_TRUE
;
6213 nsCOMPtr
<nsIJSContextStack
> stack
=
6214 do_GetService(sJSStackContractID
);
6216 JSContext
*cx
= nsnull
;
6223 nsIScriptContext
*currentCX
= nsJSUtils::GetDynamicScriptContext(cx
);
6225 if (currentCX
&& currentCX
== GetContextInternal()) {
6226 // We ignore the return value here. If setting the termination function
6227 // fails, it's better to fail to close the window than it is to crash
6228 // (which is what would tend to happen if we did this synchronously
6230 rv
= currentCX
->SetTerminationFunction(CloseWindow
,
6231 static_cast<nsIDOMWindow
*>
6233 if (NS_SUCCEEDED(rv
)) {
6234 mHavePendingClose
= PR_TRUE
;
6241 // We may have plugins on the page that have issued this close from their
6242 // event loop and because we currently destroy the plugin window with
6243 // frames, we crash. So, if we are called from Javascript, post an event
6244 // to really close the window.
6245 rv
= NS_ERROR_FAILURE
;
6246 if (!nsContentUtils::IsCallerChrome()) {
6247 rv
= nsCloseEvent::PostCloseEvent(this);
6250 if (NS_FAILED(rv
)) {
6251 ReallyCloseWindow();
6254 mHavePendingClose
= PR_TRUE
;
6262 nsGlobalWindow::ReallyCloseWindow()
6264 FORWARD_TO_OUTER_VOID(ReallyCloseWindow
, ());
6266 // Make sure we never reenter this method.
6267 mHavePendingClose
= PR_TRUE
;
6269 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
6270 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
6272 // If there's no treeOwnerAsWin, this window must already be closed.
6274 if (treeOwnerAsWin
) {
6276 // but if we're a browser window we could be in some nasty
6277 // self-destroying cascade that we should mostly ignore
6279 nsCOMPtr
<nsIDocShellTreeItem
> docItem(do_QueryInterface(mDocShell
));
6281 nsCOMPtr
<nsIBrowserDOMWindow
> bwin
;
6282 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
6283 docItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
6284 nsCOMPtr
<nsIDOMWindow
> rootWin(do_GetInterface(rootItem
));
6285 nsCOMPtr
<nsIDOMChromeWindow
> chromeWin(do_QueryInterface(rootWin
));
6287 chromeWin
->GetBrowserDOMWindow(getter_AddRefs(bwin
));
6290 /* Normally we destroy the entire window, but not if
6291 this DOM window belongs to a tabbed browser and doesn't
6292 correspond to a tab. This allows a well-behaved tab
6293 to destroy the container as it should but is a final measure
6294 to prevent an errant tab from doing so when it shouldn't.
6295 This works because we reach this code when we shouldn't only
6296 in the particular circumstance that we belong to a tab
6297 that has just been closed (and is therefore already missing
6298 from the list of browsers) (and has an unload handler
6299 that closes the window). */
6300 // XXXbz now that we have mHavePendingClose, is this needed?
6301 PRBool isTab
= PR_FALSE
;
6302 if (rootWin
== this ||
6303 !bwin
|| (bwin
->IsTabContentWindow(GetOuterWindowInternal(),
6305 treeOwnerAsWin
->Destroy();
6314 nsGlobalWindow::EnterModalState()
6316 nsGlobalWindow
* topWin
= GetTop();
6319 NS_ERROR("Uh, EnterModalState() called w/o a reachable top window?");
6324 // If there is an active ESM in this window, clear it. Otherwise, this can
6325 // cause a problem if a modal state is entered during a mouseup event.
6326 nsEventStateManager
* activeESM
=
6327 static_cast<nsEventStateManager
*>(nsEventStateManager::GetActiveEventStateManager());
6328 if (activeESM
&& activeESM
->GetPresContext()) {
6329 nsIPresShell
* activeShell
= activeESM
->GetPresContext()->GetPresShell();
6330 if (activeShell
&& (
6331 nsContentUtils::ContentIsCrossDocDescendantOf(activeShell
->GetDocument(), mDoc
) ||
6332 nsContentUtils::ContentIsCrossDocDescendantOf(mDoc
, activeShell
->GetDocument()))) {
6333 nsEventStateManager::ClearGlobalActiveContent(activeESM
);
6335 activeShell
->SetCapturingContent(nsnull
, 0);
6338 nsCOMPtr
<nsFrameSelection
> frameSelection
= activeShell
->FrameSelection();
6339 frameSelection
->SetMouseDownState(PR_FALSE
);
6344 if (topWin
->mModalStateDepth
== 0) {
6345 NS_ASSERTION(!mSuspendedDoc
, "Shouldn't have mSuspendedDoc here!");
6347 mSuspendedDoc
= do_QueryInterface(topWin
->GetExtantDocument());
6348 if (mSuspendedDoc
&& mSuspendedDoc
->EventHandlingSuppressed()) {
6349 mSuspendedDoc
->SuppressEventHandling();
6351 mSuspendedDoc
= nsnull
;
6354 topWin
->mModalStateDepth
++;
6356 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
6358 nsCOMPtr
<nsIDOMWindow
> callerWin
;
6359 nsIScriptContext
*scx
;
6360 if (cx
&& (scx
= GetScriptContextFromJSContext(cx
))) {
6361 scx
->EnterModalState();
6362 callerWin
= do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx
));
6366 mContext
->EnterModalState();
6374 nsGlobalWindow::RunPendingTimeoutsRecursive(nsGlobalWindow
*aTopWindow
,
6375 nsGlobalWindow
*aWindow
)
6377 nsGlobalWindow
*inner
;
6379 // Return early if we're frozen or have no inner window.
6380 if (!(inner
= aWindow
->GetCurrentInnerWindowInternal()) ||
6381 inner
->IsFrozen()) {
6385 inner
->RunTimeout(nsnull
);
6387 // Check again if we're frozen since running pending timeouts
6388 // could've frozen us.
6389 if (inner
->IsFrozen()) {
6393 nsCOMPtr
<nsIDOMWindowCollection
> frames
;
6394 aWindow
->GetFrames(getter_AddRefs(frames
));
6401 if (NS_FAILED(frames
->GetLength(&length
)) || !length
) {
6405 for (i
= 0; i
< length
&& aTopWindow
->mModalStateDepth
== 0; i
++) {
6406 nsCOMPtr
<nsIDOMWindow
> child
;
6407 frames
->Item(i
, getter_AddRefs(child
));
6413 nsGlobalWindow
*childWin
=
6414 static_cast<nsGlobalWindow
*>
6415 (static_cast<nsIDOMWindow
*>
6418 RunPendingTimeoutsRecursive(aTopWindow
, childWin
);
6422 class nsPendingTimeoutRunner
: public nsRunnable
6425 nsPendingTimeoutRunner(nsGlobalWindow
*aWindow
)
6428 NS_ASSERTION(mWindow
, "mWindow is null.");
6433 nsGlobalWindow::RunPendingTimeoutsRecursive(mWindow
, mWindow
);
6439 nsRefPtr
<nsGlobalWindow
> mWindow
;
6443 nsGlobalWindow::LeaveModalState(nsIDOMWindow
*aCallerWin
)
6445 nsGlobalWindow
*topWin
= GetTop();
6448 NS_ERROR("Uh, LeaveModalState() called w/o a reachable top window?");
6452 topWin
->mModalStateDepth
--;
6454 if (topWin
->mModalStateDepth
== 0) {
6455 nsCOMPtr
<nsIRunnable
> runner
= new nsPendingTimeoutRunner(topWin
);
6456 if (NS_FAILED(NS_DispatchToCurrentThread(runner
)))
6457 NS_WARNING("failed to dispatch pending timeout runnable");
6459 if (mSuspendedDoc
) {
6460 nsCOMPtr
<nsIDocument
> currentDoc
=
6461 do_QueryInterface(topWin
->GetExtantDocument());
6462 mSuspendedDoc
->UnsuppressEventHandlingAndFireEvents(currentDoc
== mSuspendedDoc
);
6463 mSuspendedDoc
= nsnull
;
6467 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
6470 nsCOMPtr
<nsIScriptGlobalObject
> sgo(do_QueryInterface(aCallerWin
));
6471 nsIScriptContext
*scx
= sgo
->GetContext();
6472 scx
->LeaveModalState();
6476 mContext
->LeaveModalState();
6479 // Remember the time of the last dialog quit.
6480 nsGlobalWindow
*inner
= topWin
->GetCurrentInnerWindowInternal();
6482 inner
->mLastDialogQuitTime
= TimeStamp::Now();
6486 nsGlobalWindow::IsInModalState()
6488 nsGlobalWindow
*topWin
= GetTop();
6491 NS_ERROR("Uh, IsInModalState() called w/o a reachable top window?");
6496 return topWin
->mModalStateDepth
!= 0;
6501 nsGlobalWindow::NotifyDOMWindowDestroyed(nsGlobalWindow
* aWindow
) {
6502 nsCOMPtr
<nsIObserverService
> observerService
=
6503 do_GetService(NS_OBSERVERSERVICE_CONTRACTID
);
6504 if (observerService
) {
6506 NotifyObservers(static_cast<nsIScriptGlobalObject
*>(aWindow
),
6507 DOM_WINDOW_DESTROYED_TOPIC
, nsnull
);
6511 class WindowDestroyedEvent
: public nsRunnable
6514 WindowDestroyedEvent(PRUint64 aID
, const char* aTopic
) :
6515 mID(aID
), mTopic(aTopic
) {}
6519 nsCOMPtr
<nsIObserverService
> observerService
=
6520 do_GetService("@mozilla.org/observer-service;1");
6521 if (observerService
) {
6522 nsCOMPtr
<nsISupportsPRUint64
> wrapper
=
6523 do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID
);
6525 wrapper
->SetData(mID
);
6526 observerService
->NotifyObservers(wrapper
, mTopic
.get(), nsnull
);
6538 nsGlobalWindow::NotifyWindowIDDestroyed(const char* aTopic
)
6540 nsRefPtr
<nsIRunnable
> runnable
= new WindowDestroyedEvent(mWindowID
, aTopic
);
6541 nsresult rv
= NS_DispatchToCurrentThread(runnable
);
6542 if (NS_SUCCEEDED(rv
)) {
6543 mNotifiedIDDestroyed
= PR_TRUE
;
6548 nsGlobalWindow::InitJavaProperties()
6550 nsIScriptContext
*scx
= GetContextInternal();
6552 if (mDidInitJavaProperties
|| IsOuterWindow() || !scx
|| !mJSObject
) {
6556 // Set mDidInitJavaProperties to true here even if initialization
6557 // can fail. If it fails, we won't try again...
6558 mDidInitJavaProperties
= PR_TRUE
;
6560 // Check whether the plugin supports NPRuntime, if so, init through
6563 nsCOMPtr
<nsIPluginHost
> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID
));
6568 mDummyJavaPluginOwner
= new nsDummyJavaPluginOwner(mDoc
);
6569 if (!mDummyJavaPluginOwner
) {
6573 host
->InstantiateDummyJavaPlugin(mDummyJavaPluginOwner
);
6575 // It's possible for us (or the Java plugin, rather) to process
6576 // events during the above call, which can lead to this window being
6577 // torn down or what not, so re-check that the dummy plugin is still
6579 if (!mDummyJavaPluginOwner
) {
6583 nsCOMPtr
<nsIPluginInstance
> dummyPlugin
;
6584 mDummyJavaPluginOwner
->GetInstance(*getter_AddRefs(dummyPlugin
));
6587 // A dummy plugin was instantiated. This means we have a Java
6588 // plugin that supports NPRuntime. For such a plugin, the plugin
6589 // instantiation code defines the Java properties for us, so we're
6595 // No NPRuntime enabled Java plugin found, null out the owner we
6596 // would have used in that case as it's no longer needed.
6597 mDummyJavaPluginOwner
= nsnull
;
6601 nsGlobalWindow::GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler
* aKey
)
6603 void* handler
= nsnull
;
6604 if (mCachedXBLPrototypeHandlers
.IsInitialized()) {
6605 mCachedXBLPrototypeHandlers
.Get(aKey
, &handler
);
6611 nsGlobalWindow::CacheXBLPrototypeHandler(nsXBLPrototypeHandler
* aKey
,
6612 nsScriptObjectHolder
& aHandler
)
6614 if (!mCachedXBLPrototypeHandlers
.IsInitialized() &&
6615 !mCachedXBLPrototypeHandlers
.Init()) {
6616 NS_ERROR("Failed to initiailize hashtable!");
6620 if (!mCachedXBLPrototypeHandlers
.Count()) {
6621 // Can't use macros to get the participant because nsGlobalChromeWindow also
6622 // runs through this code. Use QueryInterface to get the correct objects.
6623 nsXPCOMCycleCollectionParticipant
* participant
;
6624 CallQueryInterface(this, &participant
);
6625 NS_ASSERTION(participant
,
6626 "Failed to QI to nsXPCOMCycleCollectionParticipant!");
6628 nsISupports
* thisSupports
;
6629 QueryInterface(NS_GET_IID(nsCycleCollectionISupports
),
6630 reinterpret_cast<void**>(&thisSupports
));
6631 NS_ASSERTION(thisSupports
, "Failed to QI to nsCycleCollectionISupports!");
6633 nsresult rv
= nsContentUtils::HoldJSObjects(thisSupports
, participant
);
6634 if (NS_FAILED(rv
)) {
6635 NS_ERROR("nsContentUtils::HoldJSObjects failed!");
6640 mCachedXBLPrototypeHandlers
.Put(aKey
, aHandler
);
6644 nsGlobalWindow::GetFrameElement(nsIDOMElement
** aFrameElement
)
6646 FORWARD_TO_OUTER(GetFrameElement
, (aFrameElement
), NS_ERROR_NOT_INITIALIZED
);
6648 *aFrameElement
= nsnull
;
6650 nsCOMPtr
<nsIDocShellTreeItem
> docShellTI(do_QueryInterface(mDocShell
));
6656 nsCOMPtr
<nsIDocShellTreeItem
> parent
;
6657 docShellTI
->GetSameTypeParent(getter_AddRefs(parent
));
6659 if (!parent
|| parent
== docShellTI
) {
6660 // We're at a chrome boundary, don't expose the chrome iframe
6661 // element to content code.
6666 *aFrameElement
= mFrameElement
;
6667 NS_IF_ADDREF(*aFrameElement
);
6672 // Helper for converting window.showModalDialog() options (list of ';'
6673 // separated name (:|=) value pairs) to a format that's parsable by
6674 // our normal window opening code.
6677 ConvertDialogOptions(const nsAString
& aOptions
, nsAString
& aResult
)
6679 nsAString::const_iterator end
;
6680 aOptions
.EndReading(end
);
6682 nsAString::const_iterator iter
;
6683 aOptions
.BeginReading(iter
);
6685 while (iter
!= end
) {
6687 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6691 nsAString::const_iterator name_start
= iter
;
6693 // Skip characters until we find whitespace, ';', ':', or '='
6694 while (iter
!= end
&& !nsCRT::IsAsciiSpace(*iter
) &&
6701 nsAString::const_iterator name_end
= iter
;
6704 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6709 // No value found, skip the ';' and keep going.
6715 nsAString::const_iterator value_start
= iter
;
6716 nsAString::const_iterator value_end
= iter
;
6718 if (*iter
== ':' || *iter
== '=') {
6719 // We found name followed by ':' or '='. Look for a value.
6721 iter
++; // Skip the ':' or '='
6724 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6730 // Skip until we find whitespace, or ';'.
6731 while (iter
!= end
&& !nsCRT::IsAsciiSpace(*iter
) &&
6739 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6744 const nsDependentSubstring
& name
= Substring(name_start
, name_end
);
6745 const nsDependentSubstring
& value
= Substring(value_start
, value_end
);
6747 if (name
.LowerCaseEqualsLiteral("center")) {
6748 if (value
.LowerCaseEqualsLiteral("on") ||
6749 value
.LowerCaseEqualsLiteral("yes") ||
6750 value
.LowerCaseEqualsLiteral("1")) {
6751 aResult
.AppendLiteral(",centerscreen=1");
6753 } else if (name
.LowerCaseEqualsLiteral("dialogwidth")) {
6754 if (!value
.IsEmpty()) {
6755 aResult
.AppendLiteral(",width=");
6756 aResult
.Append(value
);
6758 } else if (name
.LowerCaseEqualsLiteral("dialogheight")) {
6759 if (!value
.IsEmpty()) {
6760 aResult
.AppendLiteral(",height=");
6761 aResult
.Append(value
);
6763 } else if (name
.LowerCaseEqualsLiteral("dialogtop")) {
6764 if (!value
.IsEmpty()) {
6765 aResult
.AppendLiteral(",top=");
6766 aResult
.Append(value
);
6768 } else if (name
.LowerCaseEqualsLiteral("dialogleft")) {
6769 if (!value
.IsEmpty()) {
6770 aResult
.AppendLiteral(",left=");
6771 aResult
.Append(value
);
6773 } else if (name
.LowerCaseEqualsLiteral("resizable")) {
6774 if (value
.LowerCaseEqualsLiteral("on") ||
6775 value
.LowerCaseEqualsLiteral("yes") ||
6776 value
.LowerCaseEqualsLiteral("1")) {
6777 aResult
.AppendLiteral(",resizable=1");
6779 } else if (name
.LowerCaseEqualsLiteral("scroll")) {
6780 if (value
.LowerCaseEqualsLiteral("off") ||
6781 value
.LowerCaseEqualsLiteral("no") ||
6782 value
.LowerCaseEqualsLiteral("0")) {
6783 aResult
.AppendLiteral(",scrollbars=0");
6796 nsGlobalWindow::ShowModalDialog(const nsAString
& aURI
, nsIVariant
*aArgs
,
6797 const nsAString
& aOptions
,
6798 nsIVariant
**aRetVal
)
6800 FORWARD_TO_OUTER(ShowModalDialog
, (aURI
, aArgs
, aOptions
, aRetVal
),
6801 NS_ERROR_NOT_INITIALIZED
);
6805 // Before bringing up the window/dialog, unsuppress painting and flush
6807 EnsureReflowFlushAndPaint();
6809 if (AreDialogsBlocked() || !ConfirmDialogAllowed())
6810 return NS_ERROR_NOT_AVAILABLE
;
6812 nsCOMPtr
<nsIDOMWindow
> dlgWin
;
6813 nsAutoString
options(NS_LITERAL_STRING("-moz-internal-modal=1,status=1"));
6815 ConvertDialogOptions(aOptions
, options
);
6817 options
.AppendLiteral(",scrollbars=1,centerscreen=1,resizable=0");
6820 nsresult rv
= OpenInternal(aURI
, EmptyString(), options
,
6821 PR_FALSE
, // aDialog
6822 PR_TRUE
, // aContentModal
6823 PR_TRUE
, // aCalledNoScript
6824 PR_TRUE
, // aDoJSFixups
6825 nsnull
, aArgs
, // args
6826 GetPrincipal(), // aCalleePrincipal
6827 nsnull
, // aJSCallerContext
6828 getter_AddRefs(dlgWin
));
6829 LeaveModalState(nsnull
);
6831 NS_ENSURE_SUCCESS(rv
, rv
);
6834 nsCOMPtr
<nsIPrincipal
> subjectPrincipal
;
6835 rv
= nsContentUtils::GetSecurityManager()->
6836 GetSubjectPrincipal(getter_AddRefs(subjectPrincipal
));
6837 if (NS_FAILED(rv
)) {
6841 PRBool canAccess
= PR_TRUE
;
6843 if (subjectPrincipal
) {
6844 nsCOMPtr
<nsIScriptObjectPrincipal
> objPrincipal
=
6845 do_QueryInterface(dlgWin
);
6846 nsCOMPtr
<nsIPrincipal
> dialogPrincipal
;
6849 dialogPrincipal
= objPrincipal
->GetPrincipal();
6851 rv
= subjectPrincipal
->Subsumes(dialogPrincipal
, &canAccess
);
6852 NS_ENSURE_SUCCESS(rv
, rv
);
6854 // Uh, not sure what kind of dialog this is. Prevent access to
6855 // be on the safe side...
6857 canAccess
= PR_FALSE
;
6861 nsCOMPtr
<nsPIDOMWindow
> win(do_QueryInterface(dlgWin
));
6864 nsPIDOMWindow
*inner
= win
->GetCurrentInnerWindow();
6866 nsCOMPtr
<nsIDOMModalContentWindow
> dlgInner(do_QueryInterface(inner
));
6869 dlgInner
->GetReturnValue(aRetVal
);
6873 nsRefPtr
<nsGlobalWindow
> winInternal
=
6874 static_cast<nsGlobalWindow
*>(win
.get());
6875 if (winInternal
->mCallCleanUpAfterModalDialogCloses
) {
6876 winInternal
->mCallCleanUpAfterModalDialogCloses
= PR_FALSE
;
6877 winInternal
->CleanUp(PR_TRUE
);
6884 class CommandDispatcher
: public nsRunnable
6887 CommandDispatcher(nsIDOMXULCommandDispatcher
* aDispatcher
,
6888 const nsAString
& aAction
)
6889 : mDispatcher(aDispatcher
), mAction(aAction
) {}
6893 return mDispatcher
->UpdateCommands(mAction
);
6896 nsCOMPtr
<nsIDOMXULCommandDispatcher
> mDispatcher
;
6901 nsGlobalWindow::UpdateCommands(const nsAString
& anAction
)
6903 nsPIDOMWindow
*rootWindow
= nsGlobalWindow::GetPrivateRoot();
6907 nsCOMPtr
<nsIDOMXULDocument
> xulDoc
=
6908 do_QueryInterface(rootWindow
->GetExtantDocument());
6909 // See if we contain a XUL document.
6911 // Retrieve the command dispatcher and call updateCommands on it.
6912 nsCOMPtr
<nsIDOMXULCommandDispatcher
> xulCommandDispatcher
;
6913 xulDoc
->GetCommandDispatcher(getter_AddRefs(xulCommandDispatcher
));
6914 if (xulCommandDispatcher
) {
6915 nsContentUtils::AddScriptRunner(new CommandDispatcher(xulCommandDispatcher
,
6924 nsGlobalWindow::GetBlurSuppression()
6926 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
6927 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
6928 PRBool suppress
= PR_FALSE
;
6930 treeOwnerAsWin
->GetBlurSuppression(&suppress
);
6935 nsGlobalWindow::GetSelection(nsISelection
** aSelection
)
6937 FORWARD_TO_OUTER(GetSelection
, (aSelection
), NS_ERROR_NOT_INITIALIZED
);
6939 NS_ENSURE_ARG_POINTER(aSelection
);
6940 *aSelection
= nsnull
;
6945 nsCOMPtr
<nsIPresShell
> presShell
;
6946 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
6951 *aSelection
= presShell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
6953 NS_IF_ADDREF(*aSelection
);
6959 nsGlobalWindow::Find(const nsAString
& aStr
, PRBool aCaseSensitive
,
6960 PRBool aBackwards
, PRBool aWrapAround
, PRBool aWholeWord
,
6961 PRBool aSearchInFrames
, PRBool aShowDialog
,
6964 FORWARD_TO_OUTER(Find
, (aStr
, aCaseSensitive
, aBackwards
, aWrapAround
,
6965 aWholeWord
, aSearchInFrames
, aShowDialog
, aDidFind
),
6966 NS_ERROR_NOT_INITIALIZED
);
6968 nsresult rv
= NS_OK
;
6969 *aDidFind
= PR_FALSE
;
6971 nsCOMPtr
<nsIWebBrowserFind
> finder(do_GetInterface(mDocShell
));
6972 NS_ENSURE_TRUE(finder
, NS_ERROR_FAILURE
);
6974 // Set the options of the search
6975 rv
= finder
->SetSearchString(PromiseFlatString(aStr
).get());
6976 NS_ENSURE_SUCCESS(rv
, rv
);
6977 finder
->SetMatchCase(aCaseSensitive
);
6978 finder
->SetFindBackwards(aBackwards
);
6979 finder
->SetWrapFind(aWrapAround
);
6980 finder
->SetEntireWord(aWholeWord
);
6981 finder
->SetSearchFrames(aSearchInFrames
);
6983 // the nsIWebBrowserFind is initialized to use this window
6984 // as the search root, but uses focus to set the current search
6985 // frame. If we're being called from JS (as here), this window
6986 // should be the current search frame.
6987 nsCOMPtr
<nsIWebBrowserFindInFrames
> framesFinder(do_QueryInterface(finder
));
6989 framesFinder
->SetRootSearchFrame(this); // paranoia
6990 framesFinder
->SetCurrentSearchFrame(this);
6993 // The Find API does not accept empty strings. Launch the Find Dialog.
6994 if (aStr
.IsEmpty() || aShowDialog
) {
6995 // See if the find dialog is already up using nsIWindowMediator
6996 nsCOMPtr
<nsIWindowMediator
> windowMediator
=
6997 do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
);
6999 nsCOMPtr
<nsIDOMWindowInternal
> findDialog
;
7001 if (windowMediator
) {
7002 windowMediator
->GetMostRecentWindow(NS_LITERAL_STRING("findInPage").get(),
7003 getter_AddRefs(findDialog
));
7007 // The Find dialog is already open, bring it to the top.
7008 rv
= findDialog
->Focus();
7009 } else { // Open a Find dialog
7011 nsCOMPtr
<nsIDOMWindow
> dialog
;
7012 rv
= OpenDialog(NS_LITERAL_STRING("chrome://global/content/finddialog.xul"),
7013 NS_LITERAL_STRING("_blank"),
7014 NS_LITERAL_STRING("chrome, resizable=no, dependent=yes"),
7015 finder
, getter_AddRefs(dialog
));
7019 // Launch the search with the passed in search string
7020 rv
= finder
->FindNext(aDidFind
);
7021 NS_ENSURE_SUCCESS(rv
, rv
);
7028 Is8bit(const nsAString
& aString
)
7030 static const PRUnichar EIGHT_BIT
= PRUnichar(~0x00FF);
7032 nsAString::const_iterator done_reading
;
7033 aString
.EndReading(done_reading
);
7035 // for each chunk of |aString|...
7036 PRUint32 fragmentLength
= 0;
7037 nsAString::const_iterator iter
;
7038 for (aString
.BeginReading(iter
); iter
!= done_reading
;
7039 iter
.advance(PRInt32(fragmentLength
))) {
7040 fragmentLength
= PRUint32(iter
.size_forward());
7041 const PRUnichar
* c
= iter
.get();
7042 const PRUnichar
* fragmentEnd
= c
+ fragmentLength
;
7044 // for each character in this chunk...
7045 while (c
< fragmentEnd
)
7046 if (*c
++ & EIGHT_BIT
)
7054 nsGlobalWindow::Atob(const nsAString
& aAsciiBase64String
,
7055 nsAString
& aBinaryData
)
7057 if (!Is8bit(aAsciiBase64String
)) {
7058 aBinaryData
.Truncate();
7059 return NS_ERROR_DOM_INVALID_CHARACTER_ERR
;
7062 nsresult rv
= nsXPConnect::Base64Decode(aAsciiBase64String
, aBinaryData
);
7063 if (NS_FAILED(rv
) && rv
== NS_ERROR_INVALID_ARG
) {
7064 return NS_ERROR_DOM_INVALID_CHARACTER_ERR
;
7070 nsGlobalWindow::Btoa(const nsAString
& aBinaryData
,
7071 nsAString
& aAsciiBase64String
)
7073 if (!Is8bit(aBinaryData
)) {
7074 aAsciiBase64String
.Truncate();
7075 return NS_ERROR_DOM_INVALID_CHARACTER_ERR
;
7078 return nsXPConnect::Base64Encode(aBinaryData
, aAsciiBase64String
);
7081 //*****************************************************************************
7082 // nsGlobalWindow::nsIDOMEventTarget
7083 //*****************************************************************************
7086 nsGlobalWindow::AddEventListener(const nsAString
& aType
,
7087 nsIDOMEventListener
* aListener
,
7090 FORWARD_TO_INNER_CREATE(AddEventListener
, (aType
, aListener
, aUseCapture
),
7091 NS_ERROR_NOT_AVAILABLE
);
7093 return AddEventListener(aType
, aListener
, aUseCapture
, PR_FALSE
, 0);
7097 nsGlobalWindow::RemoveEventListener(const nsAString
& aType
,
7098 nsIDOMEventListener
* aListener
,
7101 return RemoveGroupedEventListener(aType
, aListener
, aUseCapture
, nsnull
);
7105 nsGlobalWindow::DispatchEvent(nsIDOMEvent
* aEvent
, PRBool
* _retval
)
7107 FORWARD_TO_INNER(DispatchEvent
, (aEvent
, _retval
), NS_OK
);
7110 return NS_ERROR_FAILURE
;
7113 // Obtain a presentation shell
7114 nsIPresShell
*shell
= mDoc
->GetShell();
7115 nsRefPtr
<nsPresContext
> presContext
;
7117 // Retrieve the context
7118 presContext
= shell
->GetPresContext();
7121 nsEventStatus status
= nsEventStatus_eIgnore
;
7123 nsEventDispatcher::DispatchDOMEvent(GetOuterWindow(), nsnull
, aEvent
,
7124 presContext
, &status
);
7126 *_retval
= (status
!= nsEventStatus_eConsumeNoDefault
);
7130 //*****************************************************************************
7131 // nsGlobalWindow::nsIDOM3EventTarget
7132 //*****************************************************************************
7135 nsGlobalWindow::AddGroupedEventListener(const nsAString
& aType
,
7136 nsIDOMEventListener
*aListener
,
7138 nsIDOMEventGroup
*aEvtGrp
)
7140 FORWARD_TO_INNER_CREATE(AddGroupedEventListener
,
7141 (aType
, aListener
, aUseCapture
, aEvtGrp
),
7142 NS_ERROR_NOT_AVAILABLE
);
7144 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
7145 NS_ENSURE_STATE(manager
);
7146 PRInt32 flags
= aUseCapture
? NS_EVENT_FLAG_CAPTURE
: NS_EVENT_FLAG_BUBBLE
;
7147 return manager
->AddEventListenerByType(aListener
, aType
, flags
, aEvtGrp
);
7151 nsGlobalWindow::RemoveGroupedEventListener(const nsAString
& aType
,
7152 nsIDOMEventListener
*aListener
,
7154 nsIDOMEventGroup
*aEvtGrp
)
7156 FORWARD_TO_INNER(RemoveGroupedEventListener
,
7157 (aType
, aListener
, aUseCapture
, aEvtGrp
),
7158 NS_ERROR_NOT_INITIALIZED
);
7160 if (mListenerManager
) {
7161 PRInt32 flags
= aUseCapture
? NS_EVENT_FLAG_CAPTURE
: NS_EVENT_FLAG_BUBBLE
;
7163 mListenerManager
->RemoveEventListenerByType(aListener
, aType
, flags
,
7170 nsGlobalWindow::CanTrigger(const nsAString
& type
, PRBool
*_retval
)
7172 return NS_ERROR_NOT_IMPLEMENTED
;
7176 nsGlobalWindow::IsRegisteredHere(const nsAString
& type
, PRBool
*_retval
)
7178 return NS_ERROR_NOT_IMPLEMENTED
;
7182 nsGlobalWindow::AddEventListener(const nsAString
& aType
,
7183 nsIDOMEventListener
*aListener
,
7184 PRBool aUseCapture
, PRBool aWantsUntrusted
,
7185 PRUint8 optional_argc
)
7187 NS_ASSERTION(!aWantsUntrusted
|| optional_argc
> 0,
7188 "Won't check if this is chrome, you want to set "
7189 "aWantsUntrusted to PR_FALSE or make the aWantsUntrusted "
7190 "explicit by making optional_argc non-zero.");
7192 if (IsOuterWindow() && mInnerWindow
&&
7193 !nsContentUtils::CanCallerAccess(mInnerWindow
)) {
7194 return NS_ERROR_DOM_SECURITY_ERR
;
7197 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
7198 NS_ENSURE_STATE(manager
);
7200 PRInt32 flags
= aUseCapture
? NS_EVENT_FLAG_CAPTURE
: NS_EVENT_FLAG_BUBBLE
;
7202 if (aWantsUntrusted
||
7203 (optional_argc
== 0 && !nsContentUtils::IsChromeDoc(mDoc
))) {
7204 flags
|= NS_PRIV_EVENT_UNTRUSTED_PERMITTED
;
7207 return manager
->AddEventListenerByType(aListener
, aType
, flags
, nsnull
);
7211 nsGlobalWindow::AddEventListenerByIID(nsIDOMEventListener
* aListener
,
7214 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
7215 NS_ENSURE_STATE(manager
);
7216 return manager
->AddEventListenerByIID(aListener
, aIID
, NS_EVENT_FLAG_BUBBLE
);
7220 nsGlobalWindow::RemoveEventListenerByIID(nsIDOMEventListener
* aListener
,
7223 FORWARD_TO_INNER(RemoveEventListenerByIID
, (aListener
, aIID
),
7224 NS_ERROR_NOT_INITIALIZED
);
7226 if (mListenerManager
) {
7227 mListenerManager
->RemoveEventListenerByIID(aListener
, aIID
,
7228 NS_EVENT_FLAG_BUBBLE
);
7231 return NS_ERROR_FAILURE
;
7234 nsIEventListenerManager
*
7235 nsGlobalWindow::GetListenerManager(PRBool aCreateIfNotFound
)
7237 FORWARD_TO_INNER_CREATE(GetListenerManager
, (aCreateIfNotFound
), nsnull
);
7239 if (!mListenerManager
) {
7240 if (!aCreateIfNotFound
) {
7244 static NS_DEFINE_CID(kEventListenerManagerCID
,
7245 NS_EVENTLISTENERMANAGER_CID
);
7247 mListenerManager
= do_CreateInstance(kEventListenerManagerCID
);
7248 if (mListenerManager
) {
7249 mListenerManager
->SetListenerTarget(
7250 static_cast<nsPIDOMEventTarget
*>(this));
7254 return mListenerManager
;
7258 nsGlobalWindow::GetSystemEventGroup(nsIDOMEventGroup
**aGroup
)
7260 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
7261 NS_ENSURE_STATE(manager
);
7262 return manager
->GetSystemEventGroupLM(aGroup
);
7266 nsGlobalWindow::GetContextForEventHandlers(nsresult
* aRv
)
7268 nsIScriptContext
* scx
= GetContext();
7269 *aRv
= scx
? NS_OK
: NS_ERROR_UNEXPECTED
;
7273 //*****************************************************************************
7274 // nsGlobalWindow::nsPIDOMWindow
7275 //*****************************************************************************
7278 nsGlobalWindow::GetPrivateParent()
7280 FORWARD_TO_OUTER(GetPrivateParent
, (), nsnull
);
7282 nsCOMPtr
<nsIDOMWindow
> parent
;
7283 GetParent(getter_AddRefs(parent
));
7285 if (static_cast<nsIDOMWindow
*>(this) == parent
.get()) {
7286 nsCOMPtr
<nsIContent
> chromeElement(do_QueryInterface(mChromeEventHandler
));
7288 return nsnull
; // This is ok, just means a null parent.
7290 nsIDocument
* doc
= chromeElement
->GetDocument();
7292 return nsnull
; // This is ok, just means a null parent.
7294 nsIScriptGlobalObject
*globalObject
= doc
->GetScriptGlobalObject();
7296 return nsnull
; // This is ok, just means a null parent.
7298 parent
= do_QueryInterface(globalObject
);
7302 return static_cast<nsGlobalWindow
*>
7303 (static_cast<nsIDOMWindow
*>(parent
.get()));
7310 nsGlobalWindow::GetPrivateRoot()
7312 FORWARD_TO_OUTER(GetPrivateRoot
, (), nsnull
);
7314 nsCOMPtr
<nsIDOMWindow
> top
;
7315 GetTop(getter_AddRefs(top
));
7317 nsCOMPtr
<nsPIDOMWindow
> ptop
= do_QueryInterface(top
);
7318 NS_ASSERTION(ptop
, "cannot get ptop");
7322 nsIDocShell
*docShell
= ptop
->GetDocShell();
7324 // Get the chrome event handler from the doc shell, since we only
7325 // want to deal with XUL chrome handlers and not the new kind of
7326 // window root handler.
7327 nsCOMPtr
<nsIDOMEventTarget
> chromeEventHandler
;
7328 docShell
->GetChromeEventHandler(getter_AddRefs(chromeEventHandler
));
7330 nsCOMPtr
<nsIContent
> chromeElement(do_QueryInterface(mChromeEventHandler
));
7331 if (chromeElement
) {
7332 nsIDocument
* doc
= chromeElement
->GetDocument();
7334 nsIDOMWindow
*parent
= doc
->GetWindow();
7336 parent
->GetTop(getter_AddRefs(top
));
7341 return static_cast<nsGlobalWindow
*>
7342 (static_cast<nsIDOMWindow
*>(top
));
7347 nsGlobalWindow::GetLocation(nsIDOMLocation
** aLocation
)
7349 FORWARD_TO_INNER(GetLocation
, (aLocation
), NS_ERROR_NOT_INITIALIZED
);
7351 *aLocation
= nsnull
;
7353 nsIDocShell
*docShell
= GetDocShell();
7354 if (!mLocation
&& docShell
) {
7355 mLocation
= new nsLocation(docShell
);
7357 return NS_ERROR_OUT_OF_MEMORY
;
7361 NS_IF_ADDREF(*aLocation
= mLocation
);
7367 nsGlobalWindow::ActivateOrDeactivate(PRBool aActivate
)
7369 // Set / unset mIsActive on the top level window, which is used for the
7370 // :-moz-window-inactive pseudoclass.
7371 nsCOMPtr
<nsIWidget
> mainWidget
= GetMainWidget();
7375 // Get the top level widget (if the main widget is a sheet, this will
7376 // be the sheet's top (non-sheet) parent).
7377 nsCOMPtr
<nsIWidget
> topLevelWidget
= mainWidget
->GetSheetWindowParent();
7378 if (!topLevelWidget
) {
7379 topLevelWidget
= mainWidget
;
7382 // Get the top level widget's nsGlobalWindow
7383 nsCOMPtr
<nsIDOMWindowInternal
> topLevelWindow
;
7384 if (topLevelWidget
== mainWidget
) {
7385 topLevelWindow
= static_cast<nsIDOMWindowInternal
*>(this);
7387 // This is a workaround for the following problem:
7388 // When a window with an open sheet loses focus, only the sheet window
7389 // receives the NS_DEACTIVATE event. However, it's not the sheet that
7390 // should lose the active styling, but the containing top level window.
7392 topLevelWidget
->GetClientData(clientData
); // clientData is nsXULWindow
7393 nsISupports
* data
= static_cast<nsISupports
*>(clientData
);
7394 nsCOMPtr
<nsIInterfaceRequestor
> req(do_QueryInterface(data
));
7395 topLevelWindow
= do_GetInterface(req
);
7397 if (topLevelWindow
) {
7398 nsCOMPtr
<nsPIDOMWindow
> piWin(do_QueryInterface(topLevelWindow
));
7399 piWin
->SetActive(aActivate
);
7404 NotifyDocumentTree(nsIDocument
* aDocument
, void* aData
)
7406 aDocument
->EnumerateSubDocuments(NotifyDocumentTree
, nsnull
);
7407 aDocument
->DocumentStatesChanged(NS_DOCUMENT_STATE_WINDOW_INACTIVE
);
7412 nsGlobalWindow::SetActive(PRBool aActive
)
7414 nsPIDOMWindow::SetActive(aActive
);
7415 NotifyDocumentTree(mDoc
, nsnull
);
7418 void nsGlobalWindow::MaybeUpdateTouchState()
7420 FORWARD_TO_INNER_VOID(MaybeUpdateTouchState
, ());
7422 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
7424 nsCOMPtr
<nsIDOMWindow
> focusedWindow
;
7425 fm
->GetFocusedWindow(getter_AddRefs(focusedWindow
));
7427 if(this == focusedWindow
) {
7432 void nsGlobalWindow::UpdateTouchState()
7434 FORWARD_TO_INNER_VOID(UpdateTouchState
, ());
7436 nsCOMPtr
<nsIWidget
> mainWidget
= GetMainWidget();
7440 if (mMayHaveTouchEventListener
) {
7441 mainWidget
->RegisterTouchWindow();
7443 mainWidget
->UnregisterTouchWindow();
7449 nsGlobalWindow::EnableAccelerationUpdates()
7451 if (mHasAcceleration
) {
7452 nsCOMPtr
<nsIAccelerometer
> ac
=
7453 do_GetService(NS_ACCELEROMETER_CONTRACTID
);
7455 ac
->AddWindowListener(this);
7461 nsGlobalWindow::DisableAccelerationUpdates()
7463 if (mHasAcceleration
) {
7464 nsCOMPtr
<nsIAccelerometer
> ac
=
7465 do_GetService(NS_ACCELEROMETER_CONTRACTID
);
7467 ac
->RemoveWindowListener(this);
7473 nsGlobalWindow::SetChromeEventHandler(nsPIDOMEventTarget
* aChromeEventHandler
)
7475 SetChromeEventHandlerInternal(aChromeEventHandler
);
7476 if (IsOuterWindow()) {
7477 // update the chrome event handler on all our inner windows
7478 for (nsGlobalWindow
*inner
= (nsGlobalWindow
*)PR_LIST_HEAD(this);
7480 inner
= (nsGlobalWindow
*)PR_NEXT_LINK(inner
)) {
7481 NS_ASSERTION(!inner
->mOuterWindow
|| inner
->mOuterWindow
== this,
7482 "bad outer window pointer");
7483 inner
->SetChromeEventHandlerInternal(aChromeEventHandler
);
7485 } else if (mOuterWindow
) {
7486 // Need the cast to be able to call the protected method on a
7487 // superclass. We could make the method public instead, but it's really
7489 static_cast<nsGlobalWindow
*>(mOuterWindow
.get())->
7490 SetChromeEventHandlerInternal(aChromeEventHandler
);
7494 static PRBool
IsLink(nsIContent
* aContent
)
7496 nsCOMPtr
<nsIDOMHTMLAnchorElement
> anchor
= do_QueryInterface(aContent
);
7497 return (anchor
|| (aContent
&&
7498 aContent
->AttrValueIs(kNameSpaceID_XLink
, nsGkAtoms::type
,
7499 nsGkAtoms::simple
, eCaseMatters
)));
7503 nsGlobalWindow::SetFocusedNode(nsIContent
* aNode
,
7504 PRUint32 aFocusMethod
,
7507 FORWARD_TO_INNER_VOID(SetFocusedNode
, (aNode
, aFocusMethod
, aNeedsFocus
));
7509 NS_ASSERTION(!aNode
|| aNode
->GetCurrentDoc() == mDoc
,
7510 "setting focus to a node from the wrong document");
7512 if (mFocusedNode
!= aNode
) {
7513 UpdateCanvasFocus(PR_FALSE
, aNode
);
7514 mFocusedNode
= aNode
;
7515 mFocusMethod
= aFocusMethod
& FOCUSMETHOD_MASK
;
7516 mShowFocusRingForContent
= PR_FALSE
;
7520 // if a node was focused by a keypress, turn on focus rings for the
7522 if (mFocusMethod
& nsIFocusManager::FLAG_BYKEY
) {
7523 mFocusByKeyOccurred
= PR_TRUE
;
7525 // otherwise, we set mShowFocusRingForContent, as we don't want this to
7526 // be permanent for the window. On Windows, focus rings are only shown
7527 // when the FLAG_SHOWRING flag is used. On other platforms, focus rings
7528 // are only hidden for clicks on links.
7530 !(mFocusMethod
& nsIFocusManager::FLAG_BYMOUSE
) || !IsLink(aNode
) ||
7532 aFocusMethod
& nsIFocusManager::FLAG_SHOWRING
) {
7533 mShowFocusRingForContent
= PR_TRUE
;
7538 mNeedsFocus
= aNeedsFocus
;
7542 nsGlobalWindow::GetFocusMethod()
7544 FORWARD_TO_INNER(GetFocusMethod
, (), 0);
7546 return mFocusMethod
;
7550 nsGlobalWindow::ShouldShowFocusRing()
7552 FORWARD_TO_INNER(ShouldShowFocusRing
, (), PR_FALSE
);
7554 return mShowFocusRings
|| mShowFocusRingForContent
|| mFocusByKeyOccurred
;
7558 nsGlobalWindow::SetKeyboardIndicators(UIStateChangeType aShowAccelerators
,
7559 UIStateChangeType aShowFocusRings
)
7561 FORWARD_TO_INNER_VOID(SetKeyboardIndicators
, (aShowAccelerators
, aShowFocusRings
));
7563 // only change the flags that have been modified
7564 if (aShowAccelerators
!= UIStateChangeType_NoChange
)
7565 mShowAccelerators
= aShowAccelerators
== UIStateChangeType_Set
;
7566 if (aShowFocusRings
!= UIStateChangeType_NoChange
)
7567 mShowFocusRings
= aShowFocusRings
== UIStateChangeType_Set
;
7569 // propagate the indicators to child windows
7570 nsCOMPtr
<nsIDocShellTreeNode
> node
= do_QueryInterface(GetDocShell());
7572 PRInt32 childCount
= 0;
7573 node
->GetChildCount(&childCount
);
7575 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
7576 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
7577 node
->GetChildAt(i
, getter_AddRefs(childShell
));
7578 nsCOMPtr
<nsPIDOMWindow
> childWindow
= do_GetInterface(childShell
);
7580 childWindow
->SetKeyboardIndicators(aShowAccelerators
, aShowFocusRings
);
7586 // send content state notifications
7587 nsCOMPtr
<nsPresContext
> presContext
;
7589 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
7591 presContext
->EventStateManager()->
7592 SetContentState(mFocusedNode
, NS_EVENT_STATE_FOCUS
);
7599 nsGlobalWindow::GetKeyboardIndicators(PRBool
* aShowAccelerators
,
7600 PRBool
* aShowFocusRings
)
7602 FORWARD_TO_INNER_VOID(GetKeyboardIndicators
, (aShowAccelerators
, aShowFocusRings
));
7604 *aShowAccelerators
= mShowAccelerators
;
7605 *aShowFocusRings
= mShowFocusRings
;
7609 nsGlobalWindow::TakeFocus(PRBool aFocus
, PRUint32 aFocusMethod
)
7611 FORWARD_TO_INNER(TakeFocus
, (aFocus
, aFocusMethod
), PR_FALSE
);
7614 mFocusMethod
= aFocusMethod
& FOCUSMETHOD_MASK
;
7616 if (mHasFocus
!= aFocus
) {
7618 UpdateCanvasFocus(PR_TRUE
, mFocusedNode
);
7621 // if mNeedsFocus is true, then the document has not yet received a
7622 // document-level focus event. If there is a root content node, then return
7623 // true to tell the calling focus manager that a focus event is expected. If
7624 // there is no root content node, the document hasn't loaded enough yet, or
7625 // there isn't one and there is no point in firing a focus event.
7626 if (aFocus
&& mNeedsFocus
&& mDoc
&& mDoc
->GetRootElement() != nsnull
) {
7627 mNeedsFocus
= PR_FALSE
;
7631 mNeedsFocus
= PR_FALSE
;
7636 nsGlobalWindow::SetReadyForFocus()
7638 FORWARD_TO_INNER_VOID(SetReadyForFocus
, ());
7640 PRBool oldNeedsFocus
= mNeedsFocus
;
7641 mNeedsFocus
= PR_FALSE
;
7643 // update whether focus rings need to be shown using the state from the
7645 nsPIDOMWindow
* root
= GetPrivateRoot();
7647 PRBool showAccelerators
, showFocusRings
;
7648 root
->GetKeyboardIndicators(&showAccelerators
, &showFocusRings
);
7649 mShowFocusRings
= showFocusRings
;
7652 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
7654 fm
->WindowShown(this, oldNeedsFocus
);
7658 nsGlobalWindow::PageHidden()
7660 FORWARD_TO_INNER_VOID(PageHidden
, ());
7662 // the window is being hidden, so tell the focus manager that the frame is
7663 // no longer valid. Use the persisted field to determine if the document
7664 // is being destroyed.
7666 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
7668 fm
->WindowHidden(this);
7670 mNeedsFocus
= PR_TRUE
;
7674 nsGlobalWindow::DispatchAsyncHashchange()
7676 FORWARD_TO_INNER(DispatchAsyncHashchange
, (), NS_OK
);
7678 nsCOMPtr
<nsIRunnable
> event
=
7679 NS_NewRunnableMethod(this, &nsGlobalWindow::FireHashchange
);
7681 return NS_DispatchToCurrentThread(event
);
7685 nsGlobalWindow::FireHashchange()
7687 NS_ENSURE_TRUE(IsInnerWindow(), NS_ERROR_FAILURE
);
7689 // Don't do anything if the window is frozen.
7693 // Dispatch the hashchange event, which doesn't bubble and isn't cancelable,
7694 // to the outer window.
7695 return nsContentUtils::DispatchTrustedEvent(mDoc
, GetOuterWindow(),
7696 NS_LITERAL_STRING("hashchange"),
7697 PR_FALSE
, PR_FALSE
);
7701 nsGlobalWindow::DispatchSyncPopState(PRBool aIsInitial
)
7703 FORWARD_TO_INNER(DispatchSyncPopState
, (aIsInitial
), NS_OK
);
7705 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
7706 "Must be safe to run script here.");
7708 // Check that PopState hasn't been pref'ed off.
7709 if (!nsContentUtils::GetBoolPref(sPopStatePrefStr
, PR_FALSE
))
7712 nsresult rv
= NS_OK
;
7714 // Bail if the window is frozen.
7719 // Get the document's pending state object -- it contains the data we're
7720 // going to send along with the popstate event. The object is serialized as
7722 nsCOMPtr
<nsIVariant
> stateObj
;
7723 nsCOMPtr
<nsIDOMNSDocument_MOZILLA_2_0_BRANCH
> doc2
= do_QueryInterface(mDoc
);
7728 rv
= doc2
->GetMozCurrentStateObject(getter_AddRefs(stateObj
));
7729 NS_ENSURE_SUCCESS(rv
, rv
);
7731 // Obtain a presentation shell for use in creating a popstate event.
7732 nsIPresShell
*shell
= mDoc
->GetShell();
7733 nsRefPtr
<nsPresContext
> presContext
;
7735 presContext
= shell
->GetPresContext();
7738 // Create a new popstate event
7739 nsCOMPtr
<nsIDOMEvent
> domEvent
;
7740 rv
= nsEventDispatcher::CreateEvent(presContext
, nsnull
,
7741 NS_LITERAL_STRING("popstateevent"),
7742 getter_AddRefs(domEvent
));
7743 NS_ENSURE_SUCCESS(rv
, rv
);
7745 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent
= do_QueryInterface(domEvent
);
7746 NS_ENSURE_TRUE(privateEvent
, NS_ERROR_FAILURE
);
7748 // Initialize the popstate event, which does bubble but isn't cancellable.
7749 nsCOMPtr
<nsIDOMPopStateEvent_MOZILLA_2_BRANCH
> popstateEvent
=
7750 do_QueryInterface(domEvent
);
7751 rv
= popstateEvent
->InitPopStateEvent(NS_LITERAL_STRING("popstate"),
7755 NS_ENSURE_SUCCESS(rv
, rv
);
7757 rv
= privateEvent
->SetTrusted(PR_TRUE
);
7758 NS_ENSURE_SUCCESS(rv
, rv
);
7760 nsCOMPtr
<nsIDOMEventTarget
> outerWindow
=
7761 do_QueryInterface(GetOuterWindow());
7762 NS_ENSURE_TRUE(outerWindow
, NS_ERROR_UNEXPECTED
);
7764 rv
= privateEvent
->SetTarget(outerWindow
);
7765 NS_ENSURE_SUCCESS(rv
, rv
);
7767 PRBool dummy
; // default action
7768 return DispatchEvent(domEvent
, &dummy
);
7771 // Find an nsICanvasFrame under aFrame. Only search the principal
7772 // child lists. aFrame must be non-null.
7773 static nsCanvasFrame
* FindCanvasFrame(nsIFrame
* aFrame
)
7775 nsCanvasFrame
* canvasFrame
= do_QueryFrame(aFrame
);
7780 nsIFrame
* kid
= aFrame
->GetFirstChild(nsnull
);
7782 canvasFrame
= FindCanvasFrame(kid
);
7786 kid
= kid
->GetNextSibling();
7792 //-------------------------------------------------------
7793 // Tells the HTMLFrame/CanvasFrame that is now has focus
7795 nsGlobalWindow::UpdateCanvasFocus(PRBool aFocusChanged
, nsIContent
* aNewContent
)
7797 // this is called from the inner window so use GetDocShell
7798 nsIDocShell
* docShell
= GetDocShell();
7802 nsCOMPtr
<nsIEditorDocShell
> editorDocShell
= do_QueryInterface(docShell
);
7803 if (editorDocShell
) {
7805 editorDocShell
->GetEditable(&editable
);
7810 nsCOMPtr
<nsIPresShell
> presShell
;
7811 docShell
->GetPresShell(getter_AddRefs(presShell
));
7812 if (!presShell
|| !mDocument
)
7815 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
7816 Element
*rootElement
= doc
->GetRootElement();
7818 if ((mHasFocus
|| aFocusChanged
) &&
7819 (mFocusedNode
== rootElement
|| aNewContent
== rootElement
)) {
7820 nsIFrame
* frame
= rootElement
->GetPrimaryFrame();
7822 frame
= frame
->GetParent();
7823 nsCanvasFrame
* canvasFrame
= do_QueryFrame(frame
);
7825 canvasFrame
->SetHasFocus(mHasFocus
&& rootElement
== aNewContent
);
7830 // Look for the frame the hard way
7831 nsIFrame
* frame
= presShell
->GetRootFrame();
7833 nsCanvasFrame
* canvasFrame
= FindCanvasFrame(frame
);
7835 canvasFrame
->SetHasFocus(PR_FALSE
);
7841 //*****************************************************************************
7842 // nsGlobalWindow::nsIDOMViewCSS
7843 //*****************************************************************************
7846 nsGlobalWindow::GetComputedStyle(nsIDOMElement
* aElt
,
7847 const nsAString
& aPseudoElt
,
7848 nsIDOMCSSStyleDeclaration
** aReturn
)
7850 FORWARD_TO_OUTER(GetComputedStyle
, (aElt
, aPseudoElt
, aReturn
),
7851 NS_ERROR_NOT_INITIALIZED
);
7853 NS_ENSURE_ARG_POINTER(aReturn
);
7857 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
7864 nsCOMPtr
<nsIPresShell
> presShell
;
7865 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
7871 nsRefPtr
<nsComputedDOMStyle
> compStyle
;
7872 nsresult rv
= NS_NewComputedDOMStyle(aElt
, aPseudoElt
, presShell
,
7873 getter_AddRefs(compStyle
));
7874 NS_ENSURE_SUCCESS(rv
, rv
);
7876 *aReturn
= compStyle
.forget().get();
7881 //*****************************************************************************
7882 // nsGlobalWindow::nsIDOMAbstractView
7883 //*****************************************************************************
7886 nsGlobalWindow::GetDocument(nsIDOMDocumentView
** aDocumentView
)
7888 NS_ENSURE_ARG_POINTER(aDocumentView
);
7890 nsresult rv
= NS_OK
;
7893 rv
= CallQueryInterface(mDocument
, aDocumentView
);
7896 *aDocumentView
= nsnull
;
7902 //*****************************************************************************
7903 // nsGlobalWindow::nsIDOMStorageWindow
7904 //*****************************************************************************
7907 nsGlobalWindow::GetSessionStorage(nsIDOMStorage
** aSessionStorage
)
7909 FORWARD_TO_INNER(GetSessionStorage
, (aSessionStorage
), NS_ERROR_UNEXPECTED
);
7911 nsIPrincipal
*principal
= GetPrincipal();
7912 nsIDocShell
* docShell
= GetDocShell();
7914 if (!principal
|| !docShell
) {
7915 *aSessionStorage
= nsnull
;
7919 if (!nsContentUtils::GetBoolPref(kStorageEnabled
)) {
7920 *aSessionStorage
= nsnull
;
7924 if (mSessionStorage
) {
7926 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
7927 PR_LogPrint("nsGlobalWindow %p has %p sessionStorage", this, mSessionStorage
.get());
7930 nsCOMPtr
<nsPIDOMStorage
> piStorage
= do_QueryInterface(mSessionStorage
);
7932 PRBool canAccess
= piStorage
->CanAccess(principal
);
7933 NS_ASSERTION(canAccess
,
7934 "window %x owned sessionStorage "
7935 "that could not be accessed!");
7937 mSessionStorage
= nsnull
;
7942 if (!mSessionStorage
) {
7943 *aSessionStorage
= nsnull
;
7945 nsString documentURI
;
7946 nsCOMPtr
<nsIDOM3Document
> document3
= do_QueryInterface(mDoc
);
7948 document3
->GetDocumentURI(documentURI
);
7950 nsresult rv
= docShell
->GetSessionStorageForPrincipal(principal
,
7953 getter_AddRefs(mSessionStorage
));
7954 NS_ENSURE_SUCCESS(rv
, rv
);
7957 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
7958 PR_LogPrint("nsGlobalWindow %p tried to get a new sessionStorage %p", this, mSessionStorage
.get());
7962 if (!mSessionStorage
) {
7963 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
7968 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
7969 PR_LogPrint("nsGlobalWindow %p returns %p sessionStorage", this, mSessionStorage
.get());
7973 NS_ADDREF(*aSessionStorage
= mSessionStorage
);
7978 nsGlobalWindow::GetGlobalStorage(nsIDOMStorageList
** aGlobalStorage
)
7980 NS_ENSURE_ARG_POINTER(aGlobalStorage
);
7983 if (!nsContentUtils::GetBoolPref(kStorageEnabled
)) {
7984 *aGlobalStorage
= nsnull
;
7988 if (!sGlobalStorageList
) {
7989 nsresult rv
= NS_NewDOMStorageList(&sGlobalStorageList
);
7990 NS_ENSURE_SUCCESS(rv
, rv
);
7993 *aGlobalStorage
= sGlobalStorageList
;
7994 NS_IF_ADDREF(*aGlobalStorage
);
7998 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
8003 nsGlobalWindow::GetLocalStorage(nsIDOMStorage
** aLocalStorage
)
8005 FORWARD_TO_INNER(GetLocalStorage
, (aLocalStorage
), NS_ERROR_UNEXPECTED
);
8007 NS_ENSURE_ARG(aLocalStorage
);
8009 if (!nsContentUtils::GetBoolPref(kStorageEnabled
)) {
8010 *aLocalStorage
= nsnull
;
8014 if (!mLocalStorage
) {
8015 *aLocalStorage
= nsnull
;
8019 PRPackedBool unused
;
8020 if (!nsDOMStorage::CanUseStorage(&unused
))
8021 return NS_ERROR_DOM_SECURITY_ERR
;
8023 nsIPrincipal
*principal
= GetPrincipal();
8027 nsCOMPtr
<nsIDOMStorageManager
> storageManager
=
8028 do_GetService("@mozilla.org/dom/storagemanager;1", &rv
);
8029 NS_ENSURE_SUCCESS(rv
, rv
);
8031 nsString documentURI
;
8032 nsCOMPtr
<nsIDOM3Document
> document3
= do_QueryInterface(mDoc
);
8034 document3
->GetDocumentURI(documentURI
);
8036 rv
= storageManager
->GetLocalStorageForPrincipal(principal
,
8038 getter_AddRefs(mLocalStorage
));
8039 NS_ENSURE_SUCCESS(rv
, rv
);
8042 NS_ADDREF(*aLocalStorage
= mLocalStorage
);
8046 //*****************************************************************************
8047 // nsGlobalWindow::nsIDOMStorageIndexedDB
8048 //*****************************************************************************
8051 nsGlobalWindow::GetMozIndexedDB(nsIIDBFactory
** _retval
)
8054 nsCOMPtr
<mozIThirdPartyUtil
> thirdPartyUtil
=
8055 do_GetService(THIRDPARTYUTIL_CONTRACTID
);
8056 NS_ENSURE_TRUE(thirdPartyUtil
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
8058 PRBool isThirdParty
;
8059 nsresult rv
= thirdPartyUtil
->IsThirdPartyWindow(this, nsnull
,
8061 NS_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
8064 NS_WARNING("IndexedDB is not permitted in a third-party window.");
8069 mIndexedDB
= indexedDB::IDBFactory::Create(this);
8070 NS_ENSURE_TRUE(mIndexedDB
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
8073 nsCOMPtr
<nsIIDBFactory
> request(mIndexedDB
);
8074 request
.forget(_retval
);
8078 //*****************************************************************************
8079 // nsGlobalWindow::nsIInterfaceRequestor
8080 //*****************************************************************************
8083 nsGlobalWindow::GetInterface(const nsIID
& aIID
, void **aSink
)
8085 NS_ENSURE_ARG_POINTER(aSink
);
8088 if (aIID
.Equals(NS_GET_IID(nsIDocCharset
))) {
8089 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
8092 nsCOMPtr
<nsIDocCharset
> docCharset(do_QueryInterface(mDocShell
));
8094 *aSink
= docCharset
;
8095 NS_ADDREF(((nsISupports
*) *aSink
));
8099 else if (aIID
.Equals(NS_GET_IID(nsIWebNavigation
))) {
8100 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
8103 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
8106 NS_ADDREF(((nsISupports
*) *aSink
));
8111 else if (aIID
.Equals(NS_GET_IID(nsIWebBrowserPrint
))) {
8112 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
8115 nsCOMPtr
<nsIContentViewer
> viewer
;
8116 mDocShell
->GetContentViewer(getter_AddRefs(viewer
));
8118 nsCOMPtr
<nsIWebBrowserPrint
> webBrowserPrint(do_QueryInterface(viewer
));
8119 if (webBrowserPrint
) {
8120 *aSink
= webBrowserPrint
;
8121 NS_ADDREF(((nsISupports
*) *aSink
));
8127 else if (aIID
.Equals(NS_GET_IID(nsIScriptEventManager
))) {
8129 nsIScriptEventManager
* mgr
= mDoc
->GetScriptEventManager();
8132 NS_ADDREF(((nsISupports
*) *aSink
));
8136 else if (aIID
.Equals(NS_GET_IID(nsIDOMWindowUtils
)) ||
8137 aIID
.Equals(NS_GET_IID(nsIDOMWindowUtils_MOZILLA_2_0_BRANCH
))) {
8138 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
8140 nsCOMPtr
<nsISupports
> utils(do_QueryReferent(mWindowUtils
));
8143 NS_ADDREF(((nsISupports
*) *aSink
));
8145 nsDOMWindowUtils
*utilObj
= new nsDOMWindowUtils(this);
8146 nsCOMPtr
<nsISupports
> utilsIfc
=
8147 NS_ISUPPORTS_CAST(nsIDOMWindowUtils
*, utilObj
);
8149 mWindowUtils
= do_GetWeakReference(utilsIfc
);
8151 NS_ADDREF(((nsISupports
*) *aSink
));
8156 return QueryInterface(aIID
, aSink
);
8159 return *aSink
? NS_OK
: NS_ERROR_NO_INTERFACE
;
8163 nsGlobalWindow::FireOfflineStatusEvent()
8168 if (NS_IsOffline()) {
8169 name
.AssignLiteral("offline");
8171 name
.AssignLiteral("online");
8173 // The event is fired at the body element, or if there is no body element,
8175 nsCOMPtr
<nsISupports
> eventTarget
= mDoc
.get();
8176 nsCOMPtr
<nsIDOMHTMLDocument
> htmlDoc
= do_QueryInterface(mDoc
);
8178 nsCOMPtr
<nsIDOMHTMLElement
> body
;
8179 htmlDoc
->GetBody(getter_AddRefs(body
));
8185 nsCOMPtr
<nsIDOMElement
> documentElement
;
8186 mDocument
->GetDocumentElement(getter_AddRefs(documentElement
));
8187 if(documentElement
) {
8188 eventTarget
= documentElement
;
8191 nsContentUtils::DispatchTrustedEvent(mDoc
, eventTarget
, name
, PR_TRUE
, PR_FALSE
);
8195 nsGlobalWindow::Observe(nsISupports
* aSubject
, const char* aTopic
,
8196 const PRUnichar
* aData
)
8198 if (!nsCRT::strcmp(aTopic
, NS_IOSERVICE_OFFLINE_STATUS_TOPIC
)) {
8200 // if an even number of notifications arrive while we're frozen,
8201 // we don't need to fire.
8202 mFireOfflineStatusChangeEventOnThaw
= !mFireOfflineStatusChangeEventOnThaw
;
8204 FireOfflineStatusEvent();
8209 if (IsInnerWindow() && !nsCRT::strcmp(aTopic
, "dom-storage-changed")) {
8210 nsIPrincipal
*principal
;
8213 principal
= GetPrincipal();
8215 // A global storage object changed, check to see if it's one
8216 // this window can access.
8218 nsCOMPtr
<nsIURI
> codebase
;
8219 principal
->GetURI(getter_AddRefs(codebase
));
8225 nsCAutoString currentDomain
;
8226 rv
= codebase
->GetAsciiHost(currentDomain
);
8227 if (NS_FAILED(rv
)) {
8231 if (!nsDOMStorageList::CanAccessDomain(NS_ConvertUTF16toUTF8(aData
),
8233 // This window can't reach the global storage object for the
8234 // domain for which the change happened, so don't fire any
8235 // events in this window.
8241 nsAutoString
domain(aData
);
8244 // This window is frozen, rather than firing the events here,
8245 // store the domain in which the change happened and fire the
8246 // events if we're ever thawed.
8248 if (!mPendingStorageEventsObsolete
) {
8249 mPendingStorageEventsObsolete
= new nsDataHashtable
<nsStringHashKey
, PRBool
>;
8250 NS_ENSURE_TRUE(mPendingStorageEventsObsolete
, NS_ERROR_OUT_OF_MEMORY
);
8252 rv
= mPendingStorageEventsObsolete
->Init();
8253 NS_ENSURE_SUCCESS(rv
, rv
);
8256 mPendingStorageEventsObsolete
->Put(domain
, PR_TRUE
);
8261 nsRefPtr
<nsDOMStorageEventObsolete
> event
= new nsDOMStorageEventObsolete();
8262 NS_ENSURE_TRUE(event
, NS_ERROR_OUT_OF_MEMORY
);
8264 rv
= event
->InitStorageEvent(NS_LITERAL_STRING("storage"), PR_FALSE
, PR_FALSE
, domain
);
8265 NS_ENSURE_SUCCESS(rv
, rv
);
8267 nsCOMPtr
<nsIDOMHTMLDocument
> htmlDoc(do_QueryInterface(mDocument
));
8269 nsCOMPtr
<nsIDOMEventTarget
> target
;
8272 nsCOMPtr
<nsIDOMHTMLElement
> body
;
8273 htmlDoc
->GetBody(getter_AddRefs(body
));
8275 target
= do_QueryInterface(body
);
8282 PRBool defaultActionEnabled
;
8283 target
->DispatchEvent((nsIDOMStorageEventObsolete
*)event
, &defaultActionEnabled
);
8288 if (IsInnerWindow() && !nsCRT::strcmp(aTopic
, "dom-storage2-changed")) {
8289 nsIPrincipal
*principal
;
8292 nsCOMPtr
<nsIDOMStorageEvent
> event
= do_QueryInterface(aSubject
, &rv
);
8293 NS_ENSURE_SUCCESS(rv
, rv
);
8295 nsCOMPtr
<nsIDOMStorage
> changingStorage
;
8296 rv
= event
->GetStorageArea(getter_AddRefs(changingStorage
));
8297 NS_ENSURE_SUCCESS(rv
, rv
);
8299 nsCOMPtr
<nsPIDOMStorage
> pistorage
= do_QueryInterface(changingStorage
);
8300 nsPIDOMStorage::nsDOMStorageType storageType
= pistorage
->StorageType();
8302 principal
= GetPrincipal();
8303 switch (storageType
)
8305 case nsPIDOMStorage::SessionStorage
:
8307 if (SameCOMIdentity(mSessionStorage
, changingStorage
)) {
8308 // Do not fire any events for the same storage object, it's not shared
8309 // among windows, see nsGlobalWindow::GetSessionStoarge()
8313 nsCOMPtr
<nsIDOMStorage
> storage
= mSessionStorage
;
8315 nsIDocShell
* docShell
= GetDocShell();
8316 if (principal
&& docShell
) {
8317 // No need to pass documentURI here, it's only needed when we want
8318 // to create a new storage, the third paramater would be PR_TRUE
8319 docShell
->GetSessionStorageForPrincipal(principal
,
8322 getter_AddRefs(storage
));
8326 if (!pistorage
->IsForkOf(storage
)) {
8327 // This storage event is coming from a different doc shell,
8328 // i.e. it is a clone, ignore this event.
8333 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
8334 PR_LogPrint("nsGlobalWindow %p with sessionStorage %p passing event from %p", this, mSessionStorage
.get(), pistorage
.get());
8340 case nsPIDOMStorage::LocalStorage
:
8342 if (SameCOMIdentity(mLocalStorage
, changingStorage
)) {
8343 // Do not fire any events for the same storage object, it's not shared
8344 // among windows, see nsGlobalWindow::GetLocalStoarge()
8348 // Allow event fire only for the same principal storages
8349 // XXX We have to use EqualsIgnoreDomain after bug 495337 lands
8350 nsIPrincipal
*storagePrincipal
= pistorage
->Principal();
8353 rv
= storagePrincipal
->Equals(principal
, &equals
);
8354 NS_ENSURE_SUCCESS(rv
, rv
);
8366 // This window is frozen, rather than firing the events here,
8367 // store the domain in which the change happened and fire the
8368 // events if we're ever thawed.
8370 mPendingStorageEvents
.AppendObject(event
);
8374 PRBool defaultActionEnabled
;
8375 DispatchEvent((nsIDOMStorageEvent
*)event
, &defaultActionEnabled
);
8380 if (!nsCRT::strcmp(aTopic
, "offline-cache-update-added")) {
8381 if (mApplicationCache
)
8384 // Instantiate the application object now. It observes update belonging to
8385 // this window's document and correctly updates the applicationCache object
8387 nsCOMPtr
<nsIDOMOfflineResourceList
> applicationCache
;
8388 GetApplicationCache(getter_AddRefs(applicationCache
));
8389 nsCOMPtr
<nsIObserver
> observer
= do_QueryInterface(applicationCache
);
8391 observer
->Observe(aSubject
, aTopic
, aData
);
8396 NS_WARNING("unrecognized topic in nsGlobalWindow::Observe");
8397 return NS_ERROR_FAILURE
;
8400 static PLDHashOperator
8401 FirePendingStorageEvents(const nsAString
& aKey
, PRBool aData
, void *userArg
)
8403 nsGlobalWindow
*win
= static_cast<nsGlobalWindow
*>(userArg
);
8405 nsCOMPtr
<nsIDOMStorage
> storage
;
8406 win
->GetSessionStorage(getter_AddRefs(storage
));
8409 win
->Observe(storage
, "dom-storage-changed",
8410 aKey
.IsEmpty() ? nsnull
: PromiseFlatString(aKey
).get());
8413 return PL_DHASH_NEXT
;
8417 nsGlobalWindow::FireDelayedDOMEvents()
8419 FORWARD_TO_INNER(FireDelayedDOMEvents
, (), NS_ERROR_UNEXPECTED
);
8421 for (PRInt32 i
= 0; i
< mPendingStorageEvents
.Count(); ++i
) {
8422 Observe(mPendingStorageEvents
[i
], "dom-storage2-changed", nsnull
);
8425 if (mPendingStorageEventsObsolete
) {
8426 // Fire pending storage events.
8427 mPendingStorageEventsObsolete
->EnumerateRead(FirePendingStorageEvents
, this);
8429 delete mPendingStorageEventsObsolete
;
8430 mPendingStorageEventsObsolete
= nsnull
;
8433 if (mApplicationCache
) {
8434 static_cast<nsDOMOfflineResourceList
*>(mApplicationCache
.get())->FirePendingEvents();
8437 if (mFireOfflineStatusChangeEventOnThaw
) {
8438 mFireOfflineStatusChangeEventOnThaw
= PR_FALSE
;
8439 FireOfflineStatusEvent();
8442 nsCOMPtr
<nsIDocShellTreeNode
> node
=
8443 do_QueryInterface(GetDocShell());
8445 PRInt32 childCount
= 0;
8446 node
->GetChildCount(&childCount
);
8448 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
8449 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
8450 node
->GetChildAt(i
, getter_AddRefs(childShell
));
8451 NS_ASSERTION(childShell
, "null child shell");
8453 nsCOMPtr
<nsPIDOMWindow
> pWin
= do_GetInterface(childShell
);
8455 nsGlobalWindow
*win
=
8456 static_cast<nsGlobalWindow
*>
8457 (static_cast<nsPIDOMWindow
*>(pWin
));
8458 win
->FireDelayedDOMEvents();
8466 //*****************************************************************************
8467 // nsGlobalWindow: Window Control Functions
8468 //*****************************************************************************
8470 nsIDOMWindowInternal
*
8471 nsGlobalWindow::GetParentInternal()
8473 FORWARD_TO_OUTER(GetParentInternal
, (), nsnull
);
8475 nsIDOMWindowInternal
*parentInternal
= nsnull
;
8477 nsCOMPtr
<nsIDOMWindow
> parent
;
8478 GetParent(getter_AddRefs(parent
));
8480 if (parent
&& parent
!= static_cast<nsIDOMWindow
*>(this)) {
8481 nsCOMPtr
<nsIDOMWindowInternal
> tmp(do_QueryInterface(parent
));
8482 NS_ASSERTION(parent
, "Huh, parent not an nsIDOMWindowInternal?");
8484 parentInternal
= tmp
;
8487 return parentInternal
;
8492 nsGlobalWindow::CloseBlockScriptTerminationFunc(nsISupports
*aRef
)
8494 nsGlobalWindow
* pwin
= static_cast<nsGlobalWindow
*>
8495 (static_cast<nsPIDOMWindow
*>(aRef
));
8496 pwin
->mBlockScriptedClosingFlag
= PR_FALSE
;
8500 nsGlobalWindow::OpenInternal(const nsAString
& aUrl
, const nsAString
& aName
,
8501 const nsAString
& aOptions
, PRBool aDialog
,
8502 PRBool aContentModal
, PRBool aCalledNoScript
,
8503 PRBool aDoJSFixups
, nsIArray
*argv
,
8504 nsISupports
*aExtraArgument
,
8505 nsIPrincipal
*aCalleePrincipal
,
8506 JSContext
*aJSCallerContext
,
8507 nsIDOMWindow
**aReturn
)
8509 FORWARD_TO_OUTER(OpenInternal
, (aUrl
, aName
, aOptions
, aDialog
,
8510 aContentModal
, aCalledNoScript
, aDoJSFixups
,
8511 argv
, aExtraArgument
, aCalleePrincipal
,
8512 aJSCallerContext
, aReturn
),
8513 NS_ERROR_NOT_INITIALIZED
);
8518 argv
->GetLength(&argc
);
8520 NS_PRECONDITION(!aExtraArgument
|| (!argv
&& argc
== 0),
8521 "Can't pass in arguments both ways");
8522 NS_PRECONDITION(!aCalledNoScript
|| (!argv
&& argc
== 0),
8523 "Can't pass JS args when called via the noscript methods");
8524 NS_PRECONDITION(!aJSCallerContext
|| !aCalledNoScript
,
8525 "Shouldn't have caller context when called noscript");
8529 nsCOMPtr
<nsIWebBrowserChrome
> chrome
;
8530 GetWebBrowserChrome(getter_AddRefs(chrome
));
8532 // No chrome means we don't want to go through with this open call
8533 // -- see nsIWindowWatcher.idl
8534 return NS_ERROR_NOT_AVAILABLE
;
8537 NS_ASSERTION(mDocShell
, "Must have docshell here");
8539 const PRBool checkForPopup
=
8540 !aDialog
&& !WindowExists(aName
, !aCalledNoScript
);
8542 // Note: it's very important that this be an nsXPIDLCString, since we want
8543 // .get() on it to return nsnull until we write stuff to it. The window
8544 // watcher expects a null URL string if there is no URL to load.
8546 nsresult rv
= NS_OK
;
8548 // It's important to do this security check before determining whether this
8549 // window opening should be blocked, to ensure that we don't FireAbuseEvents
8550 // for a window opening that wouldn't have succeeded in the first place.
8551 if (!aUrl
.IsEmpty()) {
8552 AppendUTF16toUTF8(aUrl
, url
);
8554 /* Check whether the URI is allowed, but not for dialogs --
8555 see bug 56851. The security of this function depends on
8556 window.openDialog being inaccessible from web scripts */
8557 if (url
.get() && !aDialog
)
8558 rv
= SecurityCheckURL(url
.get());
8564 PopupControlState abuseLevel
= gPopupControlState
;
8565 if (checkForPopup
) {
8566 abuseLevel
= RevisePopupAbuseLevel(abuseLevel
);
8567 if (abuseLevel
>= openAbused
) {
8568 if (aJSCallerContext
) {
8569 // If script in some other window is doing a window.open on us and
8570 // it's being blocked, then it's OK to close us afterwards, probably.
8571 // But if we're doing a window.open on ourselves and block the popup,
8572 // prevent this window from closing until after this script terminates
8573 // so that whatever popup blocker UI the app has will be visible.
8574 if (mContext
== GetScriptContextFromJSContext(aJSCallerContext
)) {
8575 mBlockScriptedClosingFlag
= PR_TRUE
;
8576 mContext
->SetTerminationFunction(CloseBlockScriptTerminationFunc
,
8577 static_cast<nsPIDOMWindow
*>
8582 FireAbuseEvents(PR_TRUE
, PR_FALSE
, aUrl
, aName
, aOptions
);
8583 return aDoJSFixups
? NS_OK
: NS_ERROR_FAILURE
;
8587 nsCOMPtr
<nsIDOMWindow
> domReturn
;
8589 nsCOMPtr
<nsIWindowWatcher
> wwatch
=
8590 do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &rv
);
8591 NS_ENSURE_TRUE(wwatch
, rv
);
8593 NS_ConvertUTF16toUTF8
options(aOptions
);
8594 NS_ConvertUTF16toUTF8
name(aName
);
8596 const char *options_ptr
= aOptions
.IsEmpty() ? nsnull
: options
.get();
8597 const char *name_ptr
= aName
.IsEmpty() ? nsnull
: name
.get();
8600 // Reset popup state while opening a window to prevent the
8601 // current state from being active the whole time a modal
8603 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
8605 if (!aCalledNoScript
) {
8606 nsCOMPtr
<nsPIWindowWatcher
> pwwatch(do_QueryInterface(wwatch
));
8607 NS_ASSERTION(pwwatch
,
8608 "Unable to open windows from JS because window watcher "
8610 NS_ENSURE_TRUE(pwwatch
, NS_ERROR_UNEXPECTED
);
8612 rv
= pwwatch
->OpenWindowJS(this, url
.get(), name_ptr
, options_ptr
,
8614 getter_AddRefs(domReturn
));
8616 // Push a null JSContext here so that the window watcher won't screw us
8617 // up. We do NOT want this case looking at the JS context on the stack
8618 // when searching. Compare comments on
8619 // nsIDOMWindowInternal::OpenWindow and nsIWindowWatcher::OpenWindow.
8620 nsCOMPtr
<nsIJSContextStack
> stack
;
8622 if (!aContentModal
) {
8623 stack
= do_GetService(sJSStackContractID
);
8627 rv
= stack
->Push(nsnull
);
8628 NS_ENSURE_SUCCESS(rv
, rv
);
8631 rv
= wwatch
->OpenWindow(this, url
.get(), name_ptr
, options_ptr
,
8632 aExtraArgument
, getter_AddRefs(domReturn
));
8637 NS_ASSERTION(!cx
, "Unexpected JSContext popped!");
8642 NS_ENSURE_SUCCESS(rv
, rv
);
8646 domReturn
.swap(*aReturn
);
8649 nsCOMPtr
<nsIDOMChromeWindow
> chrome_win(do_QueryInterface(*aReturn
));
8651 // A new non-chrome window was created from a call to
8652 // window.open() from JavaScript, make sure there's a document in
8653 // the new window. We do this by simply asking the new window for
8654 // its document, this will synchronously create an empty document
8655 // if there is no document in the window.
8656 // XXXbz should this just use EnsureInnerWindow()?
8659 nsCOMPtr
<nsPIDOMWindow
> pidomwin(do_QueryInterface(*aReturn
));
8661 nsIDOMDocument
*temp
= pidomwin
->GetExtantDocument();
8663 NS_ASSERTION(temp
, "No document in new window!!!");
8667 nsCOMPtr
<nsIDOMDocument
> doc
;
8668 (*aReturn
)->GetDocument(getter_AddRefs(doc
));
8672 if (checkForPopup
) {
8673 if (abuseLevel
>= openControlled
) {
8674 nsGlobalWindow
*opened
= static_cast<nsGlobalWindow
*>(*aReturn
);
8675 if (!opened
->IsPopupSpamWindow()) {
8676 opened
->SetPopupSpamWindow(PR_TRUE
);
8677 ++gOpenPopupSpamCount
;
8680 if (abuseLevel
>= openAbused
)
8681 FireAbuseEvents(PR_FALSE
, PR_TRUE
, aUrl
, aName
, aOptions
);
8689 nsGlobalWindow::CloseWindow(nsISupports
*aWindow
)
8691 nsCOMPtr
<nsPIDOMWindow
> win(do_QueryInterface(aWindow
));
8693 nsGlobalWindow
* globalWin
=
8694 static_cast<nsGlobalWindow
*>
8695 (static_cast<nsPIDOMWindow
*>(win
));
8697 // Need to post an event for closing, otherwise window and
8698 // presshell etc. may get destroyed while creating frames, bug 338897.
8699 nsCloseEvent::PostCloseEvent(globalWin
);
8700 // else if OOM, better not to close. That might cause a crash.
8705 nsGlobalWindow::ClearWindowScope(nsISupports
*aWindow
)
8707 nsCOMPtr
<nsIScriptGlobalObject
> sgo(do_QueryInterface(aWindow
));
8708 nsIScriptContext
*scx
= sgo
->GetContext();
8710 scx
->ClearScope(sgo
->GetGlobalJSObject(), PR_TRUE
);
8714 //*****************************************************************************
8715 // nsGlobalWindow: Timeout Functions
8716 //*****************************************************************************
8718 PRUint32 sNestingLevel
;
8721 nsGlobalWindow::SetTimeoutOrInterval(nsIScriptTimeoutHandler
*aHandler
,
8723 PRBool aIsInterval
, PRInt32
*aReturn
)
8725 FORWARD_TO_INNER(SetTimeoutOrInterval
, (aHandler
, interval
, aIsInterval
, aReturn
),
8726 NS_ERROR_NOT_INITIALIZED
);
8728 // If we don't have a document (we could have been unloaded since
8729 // the call to setTimeout was made), do nothing.
8734 PRUint32 nestingLevel
= sNestingLevel
+ 1;
8735 if (interval
< DOMMinTimeoutValue()) {
8736 if (aIsInterval
|| nestingLevel
>= DOM_CLAMP_TIMEOUT_NESTING_LEVEL
) {
8737 // Don't allow timeouts less than DOMMinTimeoutValue() from
8740 interval
= DOMMinTimeoutValue();;
8742 else if (interval
< 0) {
8743 // Clamp negative intervals to 0.
8749 NS_ASSERTION(interval
>= 0, "DOMMinTimeoutValue() lies");
8750 PRUint32 realInterval
= interval
;
8752 // Make sure we don't proceed with a interval larger than our timer
8754 if (realInterval
> PR_IntervalToMilliseconds(DOM_MAX_TIMEOUT_VALUE
)) {
8755 realInterval
= PR_IntervalToMilliseconds(DOM_MAX_TIMEOUT_VALUE
);
8758 nsTimeout
*timeout
= new nsTimeout();
8760 return NS_ERROR_OUT_OF_MEMORY
;
8762 // Increment the timeout's reference count to represent this function's hold
8767 timeout
->mInterval
= realInterval
;
8769 timeout
->mScriptHandler
= aHandler
;
8771 // Get principal of currently executing code, save for execution of timeout.
8772 // If our principals subsume the subject principal then use the subject
8773 // principal. Otherwise, use our principal to avoid running script in
8774 // elevated principals.
8776 nsCOMPtr
<nsIPrincipal
> subjectPrincipal
;
8778 rv
= nsContentUtils::GetSecurityManager()->
8779 GetSubjectPrincipal(getter_AddRefs(subjectPrincipal
));
8780 if (NS_FAILED(rv
)) {
8783 return NS_ERROR_FAILURE
;
8786 PRBool subsumes
= PR_FALSE
;
8787 nsCOMPtr
<nsIPrincipal
> ourPrincipal
= GetPrincipal();
8789 // Note the direction of this test: We don't allow setTimeouts running with
8790 // chrome privileges on content windows, but we do allow setTimeouts running
8791 // with content privileges on chrome windows (where they can't do very much,
8793 rv
= ourPrincipal
->Subsumes(subjectPrincipal
, &subsumes
);
8794 if (NS_FAILED(rv
)) {
8797 return NS_ERROR_FAILURE
;
8801 timeout
->mPrincipal
= subjectPrincipal
;
8803 timeout
->mPrincipal
= ourPrincipal
;
8806 TimeDuration delta
= TimeDuration::FromMilliseconds(realInterval
);
8808 if (!IsFrozen() && !mTimeoutsSuspendDepth
) {
8809 // If we're not currently frozen, then we set timeout->mWhen to be the
8810 // actual firing time of the timer (i.e., now + delta). We also actually
8811 // create a timer and fire it off.
8813 timeout
->mWhen
= TimeStamp::Now() + delta
;
8815 timeout
->mTimer
= do_CreateInstance("@mozilla.org/timer;1", &rv
);
8816 if (NS_FAILED(rv
)) {
8822 rv
= timeout
->mTimer
->InitWithFuncCallback(TimerCallback
, timeout
,
8824 nsITimer::TYPE_ONE_SHOT
);
8825 if (NS_FAILED(rv
)) {
8831 // The timeout is now also held in the timer's closure.
8834 // If we are frozen, however, then we instead simply set
8835 // timeout->mTimeRemaining to be the "time remaining" in the timeout (i.e.,
8836 // the interval itself). We don't create a timer for it, since that will
8837 // happen when we are thawed and the timeout will then get a timer and run
8840 timeout
->mTimeRemaining
= delta
;
8843 timeout
->mWindow
= this;
8846 timeout
->mNestingLevel
= nestingLevel
;
8849 // No popups from timeouts by default
8850 timeout
->mPopupState
= openAbused
;
8852 if (gRunningTimeoutDepth
== 0 && gPopupControlState
< openAbused
) {
8853 // This timeout is *not* set from another timeout and it's set
8854 // while popups are enabled. Propagate the state to the timeout if
8855 // its delay (interval) is equal to or less than what
8856 // "dom.disable_open_click_delay" is set to (in ms).
8859 nsContentUtils::GetIntPref("dom.disable_open_click_delay");
8861 if (interval
<= delay
) {
8862 timeout
->mPopupState
= gPopupControlState
;
8866 InsertTimeoutIntoList(timeout
);
8868 timeout
->mPublicId
= ++mTimeoutPublicIdCounter
;
8869 *aReturn
= timeout
->mPublicId
;
8871 // Our hold on the timeout is expiring. Note that this should not actually
8872 // free the timeout (since the list should have taken ownership as well).
8880 nsGlobalWindow::SetTimeoutOrInterval(PRBool aIsInterval
, PRInt32
*aReturn
)
8882 // This needs to forward to the inner window, but since the current
8883 // inner may not be the inner in the calling scope, we need to treat
8884 // this specially here as we don't want timeouts registered in a
8885 // dying inner window to get registered and run on the current inner
8886 // window. To get this right, we need to forward this call to the
8887 // inner window that's calling window.setTimeout().
8889 if (IsOuterWindow()) {
8890 nsGlobalWindow
* callerInner
= CallerInnerWindow();
8891 NS_ENSURE_TRUE(callerInner
, NS_ERROR_NOT_AVAILABLE
);
8893 // If the caller and the callee share the same outer window,
8894 // forward to the callee inner. Else, we forward to the current
8895 // inner (e.g. someone is calling setTimeout() on a reference to
8896 // some other window).
8898 if (callerInner
->GetOuterWindow() == this &&
8899 callerInner
->IsInnerWindow()) {
8900 return callerInner
->SetTimeoutOrInterval(aIsInterval
, aReturn
);
8903 FORWARD_TO_INNER(SetTimeoutOrInterval
, (aIsInterval
, aReturn
),
8904 NS_ERROR_NOT_INITIALIZED
);
8907 PRInt32 interval
= 0;
8908 PRBool isInterval
= aIsInterval
;
8909 nsCOMPtr
<nsIScriptTimeoutHandler
> handler
;
8910 nsresult rv
= NS_CreateJSTimeoutHandler(this,
8913 getter_AddRefs(handler
));
8915 return (rv
== NS_ERROR_DOM_TYPE_ERR
) ? NS_OK
: rv
;
8917 return SetTimeoutOrInterval(handler
, interval
, isInterval
, aReturn
);
8922 nsGlobalWindow::RunTimeout(nsTimeout
*aTimeout
)
8924 // If a modal dialog is open for this window, return early. Pending
8925 // timeouts will run when the modal dialog is dismissed.
8926 if (IsInModalState() || mTimeoutsSuspendDepth
) {
8932 NS_ASSERTION(IsInnerWindow(), "Timeout running on outer window!");
8933 NS_ASSERTION(!IsFrozen(), "Timeout running on a window in the bfcache!");
8935 nsTimeout
*nextTimeout
, *timeout
;
8936 nsTimeout
*last_expired_timeout
, *last_insertion_point
;
8937 nsTimeout dummy_timeout
;
8938 PRUint32 firingDepth
= mTimeoutFiringDepth
+ 1;
8940 // Make sure that the window and the script context don't go away as
8941 // a result of running timeouts
8942 nsCOMPtr
<nsIScriptGlobalObject
> windowKungFuDeathGrip(this);
8944 // A native timer has gone off. See which of our timeouts need
8946 TimeStamp now
= TimeStamp::Now();
8949 if (aTimeout
&& aTimeout
->mWhen
> now
) {
8950 // The OS timer fired early (yikes!), and possibly out of order
8951 // too. Set |deadline| to be the time when the OS timer *should*
8952 // have fired so that any timers that *should* have fired before
8953 // aTimeout *will* be fired now. This happens most of the time on
8956 deadline
= aTimeout
->mWhen
;
8961 // The timeout list is kept in deadline order. Discover the latest
8962 // timeout whose deadline has expired. On some platforms, native
8963 // timeout events fire "early", so we need to test the timer as well
8965 last_expired_timeout
= nsnull
;
8966 for (timeout
= FirstTimeout(); IsTimeout(timeout
); timeout
= timeout
->Next()) {
8967 if (((timeout
== aTimeout
) || (timeout
->mWhen
<= deadline
)) &&
8968 (timeout
->mFiringDepth
== 0)) {
8969 // Mark any timeouts that are on the list to be fired with the
8970 // firing depth so that we can reentrantly run timeouts
8971 timeout
->mFiringDepth
= firingDepth
;
8972 last_expired_timeout
= timeout
;
8976 // Maybe the timeout that the event was fired for has been deleted
8977 // and there are no others timeouts with deadlines that make them
8978 // eligible for execution yet. Go away.
8979 if (!last_expired_timeout
) {
8983 // Insert a dummy timeout into the list of timeouts between the
8984 // portion of the list that we are about to process now and those
8985 // timeouts that will be processed in a future call to
8986 // win_run_timeout(). This dummy timeout serves as the head of the
8987 // list for any timeouts inserted as a result of running a timeout.
8988 dummy_timeout
.mFiringDepth
= firingDepth
;
8989 dummy_timeout
.mWhen
= now
;
8990 PR_INSERT_AFTER(&dummy_timeout
, last_expired_timeout
);
8992 // Don't let ClearWindowTimeouts throw away our stack-allocated
8994 dummy_timeout
.AddRef();
8995 dummy_timeout
.AddRef();
8997 last_insertion_point
= mTimeoutInsertionPoint
;
8998 mTimeoutInsertionPoint
= &dummy_timeout
;
9000 for (timeout
= FirstTimeout();
9001 timeout
!= &dummy_timeout
&& !IsFrozen();
9002 timeout
= nextTimeout
) {
9003 nextTimeout
= timeout
->Next();
9005 if (timeout
->mFiringDepth
!= firingDepth
) {
9006 // We skip the timeout since it's on the list to run at another
9012 if (mTimeoutsSuspendDepth
) {
9013 // Some timer did suspend us. Make sure the
9014 // rest of the timers get executed later.
9015 timeout
->mFiringDepth
= 0;
9019 // The timeout is on the list to run at this depth, go ahead and
9022 // Get the script context (a strong ref to prevent it going away)
9023 // for this timeout and ensure the script language is enabled.
9024 nsCOMPtr
<nsIScriptContext
> scx
= GetScriptContextInternal(
9025 timeout
->mScriptHandler
->GetScriptTypeID());
9028 // No context means this window was closed or never properly
9029 // initialized for this language.
9033 // The "scripts disabled" concept is still a little vague wrt
9034 // multiple languages. Prepare for the day when languages can be
9035 // disabled independently of the other languages...
9036 if (!scx
->GetScriptsEnabled()) {
9037 // Scripts were enabled once in this window (unless aTimeout ==
9038 // nsnull) but now scripts are disabled (we might be in
9039 // print-preview, for instance), this means we shouldn't run any
9040 // timeouts at this point.
9042 // If scripts are enabled for this language in this window again
9043 // we'll fire the timeouts that are due at that point.
9047 // This timeout is good to run
9048 nsTimeout
*last_running_timeout
= mRunningTimeout
;
9049 mRunningTimeout
= timeout
;
9050 timeout
->mRunning
= PR_TRUE
;
9052 // Push this timeout's popup control state, which should only be
9053 // eabled the first time a timeout fires that was created while
9054 // popups were enabled and with a delay less than
9055 // "dom.disable_open_click_delay".
9056 nsAutoPopupStatePusher
popupStatePusher(timeout
->mPopupState
);
9058 // Clear the timeout's popup state, if any, to prevent interval
9059 // timeouts from repeatedly opening poups.
9060 timeout
->mPopupState
= openAbused
;
9062 // Hold on to the timeout in case mExpr or mFunObj releases its
9066 ++gRunningTimeoutDepth
;
9067 ++mTimeoutFiringDepth
;
9069 PRBool trackNestingLevel
= !timeout
->mInterval
;
9070 PRUint32 nestingLevel
;
9071 if (trackNestingLevel
) {
9072 nestingLevel
= sNestingLevel
;
9073 sNestingLevel
= timeout
->mNestingLevel
;
9076 nsCOMPtr
<nsIScriptTimeoutHandler
> handler(timeout
->mScriptHandler
);
9077 void *scriptObject
= handler
->GetScriptObject();
9078 if (!scriptObject
) {
9079 // Evaluate the timeout expression.
9080 const PRUnichar
*script
= handler
->GetHandlerText();
9081 NS_ASSERTION(script
, "timeout has no script nor handler text!");
9083 const char *filename
= nsnull
;
9084 PRUint32 lineNo
= 0;
9085 handler
->GetLocation(&filename
, &lineNo
);
9087 NS_TIME_FUNCTION_MARK("(file: %s, line: %d)", filename
, lineNo
);
9089 PRBool is_undefined
;
9090 scx
->EvaluateString(nsDependentString(script
),
9091 GetScriptGlobal(handler
->GetScriptTypeID()),
9092 timeout
->mPrincipal
, filename
, lineNo
,
9093 handler
->GetScriptVersion(), nsnull
,
9096 // Let the script handler know about the "secret" final argument that
9097 // indicates timeout lateness in milliseconds
9098 TimeDuration lateness
= now
- timeout
->mWhen
;
9100 handler
->SetLateness(lateness
.ToMilliseconds());
9102 nsCOMPtr
<nsIVariant
> dummy
;
9103 nsCOMPtr
<nsISupports
> me(static_cast<nsIDOMWindow
*>(this));
9104 scx
->CallEventHandler(me
,
9105 GetScriptGlobal(handler
->GetScriptTypeID()),
9106 scriptObject
, handler
->GetArgv(),
9107 // XXXmarkh - consider allowing CallEventHandler to
9109 getter_AddRefs(dummy
));
9112 handler
= nsnull
; // drop reference before dropping timeout refs.
9114 if (trackNestingLevel
) {
9115 sNestingLevel
= nestingLevel
;
9118 --mTimeoutFiringDepth
;
9119 --gRunningTimeoutDepth
;
9121 mRunningTimeout
= last_running_timeout
;
9122 timeout
->mRunning
= PR_FALSE
;
9124 // We ignore any failures from calling EvaluateString() or
9125 // CallEventHandler() on the context here since we're in a loop
9126 // where we're likely to be running timeouts whose OS timers
9127 // didn't fire in time and we don't want to not fire those timers
9128 // now just because execution of one timer failed. We can't
9129 // propagate the error to anyone who cares about it from this
9130 // point anyway, and the script context should have already reported
9131 // the script error in the usual way - so we just drop it.
9133 // If all timeouts were cleared and |timeout != aTimeout| then
9134 // |timeout| may be the last reference to the timeout so check if
9135 // it was cleared before releasing it.
9136 PRBool timeout_was_cleared
= timeout
->mCleared
;
9140 if (timeout_was_cleared
) {
9141 // The running timeout's window was cleared, this means that
9142 // ClearAllTimeouts() was called from a *nested* call, possibly
9143 // through a timeout that fired while a modal (to this window)
9144 // dialog was open or through other non-obvious paths.
9146 mTimeoutInsertionPoint
= last_insertion_point
;
9151 PRBool isInterval
= PR_FALSE
;
9153 // If we have a regular interval timer, we re-schedule the
9154 // timeout, accounting for clock drift.
9155 if (timeout
->mInterval
) {
9156 // Compute time to next timeout for interval timer.
9157 // Make sure nextInterval is at least DOMMinTimeoutValue().
9158 TimeDuration nextInterval
=
9159 TimeDuration::FromMilliseconds(NS_MAX(timeout
->mInterval
,
9160 PRUint32(DOMMinTimeoutValue())));
9162 // If we're running pending timeouts because they've been temporarily
9163 // disabled (!aTimeout), set the next interval to be relative to "now",
9164 // and not to when the timeout that was pending should have fired. Also
9165 // check if the next interval timeout is overdue. If so, then restart
9166 // the interval from now.
9167 TimeStamp firingTime
;
9168 if (!aTimeout
|| timeout
->mWhen
+ nextInterval
<= now
)
9169 firingTime
= now
+ nextInterval
;
9171 firingTime
= timeout
->mWhen
+ nextInterval
;
9173 TimeDuration delay
= firingTime
- TimeStamp::Now();
9175 // And make sure delay is nonnegative; that might happen if the timer
9176 // thread is firing our timers somewhat early.
9177 if (delay
< TimeDuration(0)) {
9178 delay
= TimeDuration(0);
9181 if (timeout
->mTimer
) {
9182 timeout
->mWhen
= firingTime
;
9184 // Reschedule the OS timer. Don't bother returning any error
9185 // codes if this fails since the callers of this method
9186 // doesn't care about them nobody who cares about them
9189 // Make sure to cast the unsigned PR_USEC_PER_MSEC to signed
9190 // PRTime to make the division do the right thing on 64-bit
9191 // platforms whether delay is positive or negative (which we
9192 // know is always positive here, but cast anyways for
9194 nsresult rv
= timeout
->mTimer
->
9195 InitWithFuncCallback(TimerCallback
, timeout
,
9196 delay
.ToMilliseconds(),
9197 nsITimer::TYPE_ONE_SHOT
);
9199 if (NS_FAILED(rv
)) {
9200 NS_ERROR("Error initializing timer for DOM timeout!");
9202 // We failed to initialize the new OS timer, this timer does
9203 // us no good here so we just cancel it (just in case) and
9204 // null out the pointer to the OS timer, this will release the
9205 // OS timer. As we continue executing the code below we'll end
9206 // up deleting the timeout since it's not an interval timeout
9207 // any more (since timeout->mTimer == nsnull).
9208 timeout
->mTimer
->Cancel();
9209 timeout
->mTimer
= nsnull
;
9211 // Now that the OS timer no longer has a reference to the
9212 // timeout we need to drop that reference.
9216 NS_ASSERTION(IsFrozen() || mTimeoutsSuspendDepth
,
9217 "How'd our timer end up null if we're not frozen or "
9220 timeout
->mTimeRemaining
= delay
;
9221 isInterval
= PR_TRUE
;
9225 if (timeout
->mTimer
) {
9226 if (timeout
->mInterval
) {
9227 isInterval
= PR_TRUE
;
9229 // The timeout still has an OS timer, and it's not an
9230 // interval, that means that the OS timer could still fire (if
9231 // it didn't already, i.e. aTimeout == timeout), cancel the OS
9232 // timer and release its reference to the timeout.
9233 timeout
->mTimer
->Cancel();
9234 timeout
->mTimer
= nsnull
;
9240 // Running a timeout can cause another timeout to be deleted, so
9241 // we need to reset the pointer to the following timeout.
9242 nextTimeout
= timeout
->Next();
9244 PR_REMOVE_LINK(timeout
);
9247 // Reschedule an interval timeout. Insert interval timeout
9248 // onto list sorted in deadline order.
9250 InsertTimeoutIntoList(timeout
);
9253 // Release the timeout struct since it's possibly out of the list
9257 // Take the dummy timeout off the head of the list
9258 PR_REMOVE_LINK(&dummy_timeout
);
9260 mTimeoutInsertionPoint
= last_insertion_point
;
9264 nsTimeout::Release()
9269 // language specific cleanup done as mScriptHandler destructs...
9271 // Kill the timer if it is still alive.
9289 nsGlobalWindow::ClearTimeoutOrInterval(PRInt32 aTimerID
)
9291 FORWARD_TO_INNER(ClearTimeoutOrInterval
, (aTimerID
), NS_ERROR_NOT_INITIALIZED
);
9293 PRUint32 public_id
= (PRUint32
)aTimerID
;
9296 for (timeout
= FirstTimeout();
9298 timeout
= timeout
->Next()) {
9299 if (timeout
->mPublicId
== public_id
) {
9300 if (timeout
->mRunning
) {
9301 /* We're running from inside the timeout. Mark this
9302 timeout for deferred deletion by the code in
9304 timeout
->mInterval
= 0;
9307 /* Delete the timeout from the pending timeout list */
9308 PR_REMOVE_LINK(timeout
);
9310 if (timeout
->mTimer
) {
9311 timeout
->mTimer
->Cancel();
9312 timeout
->mTimer
= nsnull
;
9324 // A JavaScript specific version.
9326 nsGlobalWindow::ClearTimeoutOrInterval()
9328 FORWARD_TO_INNER(ClearTimeoutOrInterval
, (), NS_ERROR_NOT_INITIALIZED
);
9330 nsresult rv
= NS_OK
;
9331 nsAXPCNativeCallContext
*ncc
= nsnull
;
9333 rv
= nsContentUtils::XPConnect()->
9334 GetCurrentNativeCallContext(&ncc
);
9335 NS_ENSURE_SUCCESS(rv
, rv
);
9338 return NS_ERROR_NOT_AVAILABLE
;
9340 JSContext
*cx
= nsnull
;
9342 rv
= ncc
->GetJSContext(&cx
);
9343 NS_ENSURE_SUCCESS(rv
, rv
);
9347 ncc
->GetArgc(&argc
);
9350 // No arguments, return early.
9355 jsval
*argv
= nsnull
;
9357 ncc
->GetArgvPtr(&argv
);
9361 JSAutoRequest
ar(cx
);
9363 // XXXjst: Can we deal with this w/o using GetCurrentNativeCallContext()
9364 if (argv
[0] == JSVAL_VOID
|| !::JS_ValueToInt32(cx
, argv
[0], &timer_id
) ||
9366 // Undefined or non-positive number passed as argument, return
9367 // early. Make sure that JS_ValueToInt32 didn't set an exception.
9369 ::JS_ClearPendingException(cx
);
9373 return ClearTimeoutOrInterval(timer_id
);
9377 nsGlobalWindow::ClearAllTimeouts()
9379 nsTimeout
*timeout
, *nextTimeout
;
9381 for (timeout
= FirstTimeout(); IsTimeout(timeout
); timeout
= nextTimeout
) {
9382 /* If RunTimeout() is higher up on the stack for this
9383 window, e.g. as a result of document.write from a timeout,
9384 then we need to reset the list insertion point for
9385 newly-created timeouts in case the user adds a timeout,
9386 before we pop the stack back to RunTimeout. */
9387 if (mRunningTimeout
== timeout
)
9388 mTimeoutInsertionPoint
= nsnull
;
9390 nextTimeout
= timeout
->Next();
9392 if (timeout
->mTimer
) {
9393 timeout
->mTimer
->Cancel();
9394 timeout
->mTimer
= nsnull
;
9396 // Drop the count since the timer isn't going to hold on
9401 // Set timeout->mCleared to true to indicate that the timeout was
9402 // cleared and taken out of the list of timeouts
9403 timeout
->mCleared
= PR_TRUE
;
9405 // Drop the count since we're removing it from the list.
9409 // Clear out our list
9410 PR_INIT_CLIST(&mTimeouts
);
9414 nsGlobalWindow::InsertTimeoutIntoList(nsTimeout
*aTimeout
)
9416 NS_ASSERTION(IsInnerWindow(),
9417 "InsertTimeoutIntoList() called on outer window!");
9419 // Start at mLastTimeout and go backwards. Don't go further than
9420 // mTimeoutInsertionPoint, though. This optimizes for the common case of
9421 // insertion at the end.
9422 nsTimeout
* prevSibling
;
9423 for (prevSibling
= LastTimeout();
9424 IsTimeout(prevSibling
) && prevSibling
!= mTimeoutInsertionPoint
&&
9425 // This condition needs to match the one in SetTimeoutOrInterval that
9426 // determines whether to set mWhen or mTimeRemaining.
9427 ((IsFrozen() || mTimeoutsSuspendDepth
) ?
9428 prevSibling
->mTimeRemaining
> aTimeout
->mTimeRemaining
:
9429 prevSibling
->mWhen
> aTimeout
->mWhen
);
9430 prevSibling
= prevSibling
->Prev()) {
9431 /* Do nothing; just searching */
9434 // Now link in aTimeout after prevSibling.
9435 PR_INSERT_AFTER(aTimeout
, prevSibling
);
9437 aTimeout
->mFiringDepth
= 0;
9439 // Increment the timeout's reference count since it's now held on to
9446 nsGlobalWindow::TimerCallback(nsITimer
*aTimer
, void *aClosure
)
9448 nsTimeout
*timeout
= (nsTimeout
*)aClosure
;
9450 // Hold on to the timeout to ensure it doesn't go away while it's
9451 // being handled (aka kungFuDeathGrip).
9454 timeout
->mWindow
->RunTimeout(timeout
);
9456 // Drop our reference to the timeout now that we're done with it.
9460 //*****************************************************************************
9461 // nsGlobalWindow: Helper Functions
9462 //*****************************************************************************
9465 nsGlobalWindow::GetTreeOwner(nsIDocShellTreeOwner
**aTreeOwner
)
9467 FORWARD_TO_OUTER(GetTreeOwner
, (aTreeOwner
), NS_ERROR_NOT_INITIALIZED
);
9469 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
9471 // If there's no docShellAsItem, this window must have been closed,
9472 // in that case there is no tree owner.
9474 if (!docShellAsItem
) {
9475 *aTreeOwner
= nsnull
;
9480 return docShellAsItem
->GetTreeOwner(aTreeOwner
);
9484 nsGlobalWindow::GetTreeOwner(nsIBaseWindow
**aTreeOwner
)
9486 FORWARD_TO_OUTER(GetTreeOwner
, (aTreeOwner
), NS_ERROR_NOT_INITIALIZED
);
9488 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
9489 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
9491 // If there's no docShellAsItem, this window must have been closed,
9492 // in that case there is no tree owner.
9494 if (docShellAsItem
) {
9495 docShellAsItem
->GetTreeOwner(getter_AddRefs(treeOwner
));
9499 *aTreeOwner
= nsnull
;
9503 return CallQueryInterface(treeOwner
, aTreeOwner
);
9507 nsGlobalWindow::GetWebBrowserChrome(nsIWebBrowserChrome
**aBrowserChrome
)
9509 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
9510 GetTreeOwner(getter_AddRefs(treeOwner
));
9512 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome(do_GetInterface(treeOwner
));
9513 NS_IF_ADDREF(*aBrowserChrome
= browserChrome
);
9518 nsIScrollableFrame
*
9519 nsGlobalWindow::GetScrollFrame()
9521 FORWARD_TO_OUTER(GetScrollFrame
, (), nsnull
);
9527 nsCOMPtr
<nsIPresShell
> presShell
;
9528 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
9530 return presShell
->GetRootScrollFrameAsScrollable();
9536 nsGlobalWindow::BuildURIfromBase(const char *aURL
, nsIURI
**aBuiltURI
,
9537 PRBool
*aFreeSecurityPass
,
9538 JSContext
**aCXused
)
9540 nsIScriptContext
*scx
= GetContextInternal();
9541 JSContext
*cx
= nsnull
;
9543 *aBuiltURI
= nsnull
;
9544 *aFreeSecurityPass
= PR_FALSE
;
9549 NS_ASSERTION(scx
, "opening window missing its context");
9550 NS_ASSERTION(mDocument
, "opening window missing its document");
9551 if (!scx
|| !mDocument
)
9552 return NS_ERROR_FAILURE
;
9554 nsCOMPtr
<nsIDOMChromeWindow
> chrome_win
=
9555 do_QueryInterface(static_cast<nsIDOMWindow
*>(this));
9557 if (nsContentUtils::IsCallerChrome() && !chrome_win
) {
9558 // If open() is called from chrome on a non-chrome window, we'll
9559 // use the context from the window on which open() is being called
9560 // to prevent giving chrome priveleges to new windows opened in
9561 // such a way. This also makes us get the appropriate base URI for
9562 // the below URI resolution code.
9564 cx
= (JSContext
*)scx
->GetNativeContext();
9566 // get the JSContext from the call stack
9567 nsCOMPtr
<nsIThreadJSContextStack
> stack(do_GetService(sJSStackContractID
));
9572 /* resolve the URI, which could be relative to the calling window
9573 (note the algorithm to get the base URI should match the one
9574 used to actually kick off the load in nsWindowWatcher.cpp). */
9575 nsCAutoString
charset(NS_LITERAL_CSTRING("UTF-8")); // default to utf-8
9576 nsIURI
* baseURI
= nsnull
;
9577 nsCOMPtr
<nsIURI
> uriToLoad
;
9578 nsCOMPtr
<nsIDOMWindow
> sourceWindow
;
9581 nsIScriptContext
*scriptcx
= nsJSUtils::GetDynamicScriptContext(cx
);
9583 sourceWindow
= do_QueryInterface(scriptcx
->GetGlobalObject());
9586 if (!sourceWindow
) {
9587 sourceWindow
= do_QueryInterface(NS_ISUPPORTS_CAST(nsIDOMWindow
*, this));
9588 *aFreeSecurityPass
= PR_TRUE
;
9592 nsCOMPtr
<nsIDOMDocument
> domDoc
;
9593 sourceWindow
->GetDocument(getter_AddRefs(domDoc
));
9594 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(domDoc
));
9596 baseURI
= doc
->GetDocBaseURI();
9597 charset
= doc
->GetDocumentCharacterSet();
9603 return NS_NewURI(aBuiltURI
, nsDependentCString(aURL
), charset
.get(), baseURI
);
9607 nsGlobalWindow::SecurityCheckURL(const char *aURL
)
9611 nsCOMPtr
<nsIURI
> uri
;
9613 if (NS_FAILED(BuildURIfromBase(aURL
, getter_AddRefs(uri
), &freePass
, &cx
)))
9614 return NS_ERROR_FAILURE
;
9616 if (!freePass
&& NS_FAILED(nsContentUtils::GetSecurityManager()->
9617 CheckLoadURIFromScript(cx
, uri
)))
9618 return NS_ERROR_FAILURE
;
9624 nsGlobalWindow::FlushPendingNotifications(mozFlushType aType
)
9627 mDoc
->FlushPendingNotifications(aType
);
9632 nsGlobalWindow::EnsureSizeUpToDate()
9634 // If we're a subframe, make sure our size is up to date. It's OK that this
9635 // crosses the content/chrome boundary, since chrome can have pending reflows
9637 nsGlobalWindow
*parent
=
9638 static_cast<nsGlobalWindow
*>(GetPrivateParent());
9640 parent
->FlushPendingNotifications(Flush_Layout
);
9645 nsGlobalWindow::SaveWindowState(nsISupports
**aState
)
9647 NS_PRECONDITION(IsOuterWindow(), "Can't save the inner window's state");
9651 if (!mContext
|| !mJSObject
) {
9652 // The window may be getting torn down; don't bother saving state.
9656 nsGlobalWindow
*inner
= GetCurrentInnerWindowInternal();
9657 NS_ASSERTION(inner
, "No inner window to save");
9659 // Don't do anything else to this inner window! After this point, all
9660 // calls to SetTimeoutOrInterval will create entries in the timeout
9661 // list that will only run after this window has come out of the bfcache.
9662 // Also, while we're frozen, we won't dispatch online/offline events
9666 // Remember the outer window's prototype.
9667 JSContext
*cx
= (JSContext
*)mContext
->GetNativeContext();
9668 JSAutoRequest
req(cx
);
9670 nsIXPConnect
*xpc
= nsContentUtils::XPConnect();
9672 nsCOMPtr
<nsIClassInfo
> ci
=
9673 do_QueryInterface((nsIScriptGlobalObject
*)this);
9674 nsCOMPtr
<nsIXPConnectJSObjectHolder
> proto
;
9675 nsresult rv
= xpc
->GetWrappedNativePrototype(cx
, mJSObject
, ci
,
9676 getter_AddRefs(proto
));
9677 NS_ENSURE_SUCCESS(rv
, rv
);
9679 JSObject
*realProto
= JS_GetPrototype(cx
, mJSObject
);
9680 nsCOMPtr
<nsIXPConnectJSObjectHolder
> realProtoHolder
;
9682 rv
= xpc
->HoldObject(cx
, realProto
, getter_AddRefs(realProtoHolder
));
9683 NS_ENSURE_SUCCESS(rv
, rv
);
9686 nsCOMPtr
<nsISupports
> state
= new WindowStateHolder(inner
,
9691 NS_ENSURE_TRUE(state
, NS_ERROR_OUT_OF_MEMORY
);
9694 proto
->GetJSObject(&wnProto
);
9695 if (!JS_SetPrototype(cx
, mJSObject
, wnProto
)) {
9696 return NS_ERROR_FAILURE
;
9699 #ifdef DEBUG_PAGE_CACHE
9700 printf("saving window state, state = %p\n", (void*)state
);
9703 state
.swap(*aState
);
9708 nsGlobalWindow::RestoreWindowState(nsISupports
*aState
)
9710 NS_ASSERTION(IsOuterWindow(), "Cannot restore an inner window");
9712 if (!mContext
|| !mJSObject
) {
9713 // The window may be getting torn down; don't bother restoring state.
9717 nsCOMPtr
<WindowStateHolder
> holder
= do_QueryInterface(aState
);
9718 NS_ENSURE_TRUE(holder
, NS_ERROR_FAILURE
);
9720 #ifdef DEBUG_PAGE_CACHE
9721 printf("restoring window state, state = %p\n", (void*)holder
);
9724 // And we're ready to go!
9725 nsGlobalWindow
*inner
= GetCurrentInnerWindowInternal();
9727 // if a link is focused, refocus with the FLAG_SHOWRING flag set. This makes
9728 // it easy to tell which link was last clicked when going back a page.
9729 nsIContent
* focusedNode
= inner
->GetFocusedNode();
9730 if (IsLink(focusedNode
)) {
9731 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
9733 nsCOMPtr
<nsIDOMElement
> focusedElement(do_QueryInterface(focusedNode
));
9734 fm
->SetFocus(focusedElement
, nsIFocusManager::FLAG_NOSCROLL
|
9735 nsIFocusManager::FLAG_SHOWRING
);
9741 holder
->DidRestoreWindow();
9747 nsGlobalWindow::SuspendTimeouts(PRUint32 aIncrease
,
9748 PRBool aFreezeChildren
)
9750 FORWARD_TO_INNER_VOID(SuspendTimeouts
, (aIncrease
, aFreezeChildren
));
9752 PRBool suspended
= (mTimeoutsSuspendDepth
!= 0);
9753 mTimeoutsSuspendDepth
+= aIncrease
;
9756 DisableAccelerationUpdates();
9758 nsDOMThreadService
* dts
= nsDOMThreadService::get();
9760 dts
->SuspendWorkersForGlobal(static_cast<nsIScriptGlobalObject
*>(this));
9763 TimeStamp now
= TimeStamp::Now();
9764 for (nsTimeout
*t
= FirstTimeout(); IsTimeout(t
); t
= t
->Next()) {
9765 // Set mTimeRemaining to be the time remaining for this timer.
9767 t
->mTimeRemaining
= t
->mWhen
- now
;
9769 t
->mTimeRemaining
= TimeDuration(0);
9771 // Drop the XPCOM timer; we'll reschedule when restoring the state.
9773 t
->mTimer
->Cancel();
9776 // Drop the reference that the timer's closure had on this timeout, we'll
9777 // add it back in ResumeTimeouts. Note that it shouldn't matter that we're
9778 // passing null for the context, since this shouldn't actually release this
9785 // Suspend our children as well.
9786 nsCOMPtr
<nsIDocShellTreeNode
> node(do_QueryInterface(GetDocShell()));
9788 PRInt32 childCount
= 0;
9789 node
->GetChildCount(&childCount
);
9791 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
9792 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
9793 node
->GetChildAt(i
, getter_AddRefs(childShell
));
9794 NS_ASSERTION(childShell
, "null child shell");
9796 nsCOMPtr
<nsPIDOMWindow
> pWin
= do_GetInterface(childShell
);
9798 nsGlobalWindow
*win
=
9799 static_cast<nsGlobalWindow
*>
9800 (static_cast<nsPIDOMWindow
*>(pWin
));
9801 NS_ASSERTION(win
->IsOuterWindow(), "Expected outer window");
9802 nsGlobalWindow
* inner
= win
->GetCurrentInnerWindowInternal();
9804 // This is a bit hackish. Only freeze/suspend windows which are truly our
9806 nsCOMPtr
<nsIContent
> frame
= do_QueryInterface(pWin
->GetFrameElementInternal());
9807 if (!mDoc
|| !frame
|| mDoc
!= frame
->GetOwnerDoc() || !inner
) {
9811 win
->SuspendTimeouts(aIncrease
, aFreezeChildren
);
9813 if (inner
&& aFreezeChildren
) {
9822 nsGlobalWindow::ResumeTimeouts(PRBool aThawChildren
)
9824 FORWARD_TO_INNER(ResumeTimeouts
, (), NS_ERROR_NOT_INITIALIZED
);
9826 NS_ASSERTION(mTimeoutsSuspendDepth
, "Mismatched calls to ResumeTimeouts!");
9827 --mTimeoutsSuspendDepth
;
9828 PRBool shouldResume
= (mTimeoutsSuspendDepth
== 0);
9832 EnableAccelerationUpdates();
9834 nsDOMThreadService
* dts
= nsDOMThreadService::get();
9836 dts
->ResumeWorkersForGlobal(static_cast<nsIScriptGlobalObject
*>(this));
9839 // Restore all of the timeouts, using the stored time remaining
9840 // (stored in timeout->mTimeRemaining).
9842 TimeStamp now
= TimeStamp::Now();
9845 PRBool _seenDummyTimeout
= PR_FALSE
;
9848 for (nsTimeout
*t
= FirstTimeout(); IsTimeout(t
); t
= t
->Next()) {
9849 // There's a chance we're being called with RunTimeout on the stack in which
9850 // case we have a dummy timeout in the list that *must not* be resumed. It
9851 // can be identified by a null mWindow.
9854 NS_ASSERTION(!_seenDummyTimeout
, "More than one dummy timeout?!");
9855 _seenDummyTimeout
= PR_TRUE
;
9860 // XXXbz the combination of the way |delay| and |t->mWhen| are set here
9861 // makes no sense. Are we trying to impose that min timeout value or
9864 NS_MAX(PRInt32(t
->mTimeRemaining
.ToMilliseconds()),
9865 DOMMinTimeoutValue());
9867 // Set mWhen back to the time when the timer is supposed to
9869 t
->mWhen
= now
+ t
->mTimeRemaining
;
9871 t
->mTimer
= do_CreateInstance("@mozilla.org/timer;1");
9872 NS_ENSURE_TRUE(t
->mTimer
, NS_ERROR_OUT_OF_MEMORY
);
9874 rv
= t
->mTimer
->InitWithFuncCallback(TimerCallback
, t
, delay
,
9875 nsITimer::TYPE_ONE_SHOT
);
9876 if (NS_FAILED(rv
)) {
9881 // Add a reference for the new timer's closure.
9886 // Resume our children as well.
9887 nsCOMPtr
<nsIDocShellTreeNode
> node
=
9888 do_QueryInterface(GetDocShell());
9890 PRInt32 childCount
= 0;
9891 node
->GetChildCount(&childCount
);
9893 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
9894 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
9895 node
->GetChildAt(i
, getter_AddRefs(childShell
));
9896 NS_ASSERTION(childShell
, "null child shell");
9898 nsCOMPtr
<nsPIDOMWindow
> pWin
= do_GetInterface(childShell
);
9900 nsGlobalWindow
*win
=
9901 static_cast<nsGlobalWindow
*>
9902 (static_cast<nsPIDOMWindow
*>(pWin
));
9904 NS_ASSERTION(win
->IsOuterWindow(), "Expected outer window");
9905 nsGlobalWindow
* inner
= win
->GetCurrentInnerWindowInternal();
9907 // This is a bit hackish. Only thaw/resume windows which are truly our
9909 nsCOMPtr
<nsIContent
> frame
= do_QueryInterface(pWin
->GetFrameElementInternal());
9910 if (!mDoc
|| !frame
|| mDoc
!= frame
->GetOwnerDoc() || !inner
) {
9914 if (inner
&& aThawChildren
) {
9918 rv
= win
->ResumeTimeouts(aThawChildren
);
9919 NS_ENSURE_SUCCESS(rv
, rv
);
9928 nsGlobalWindow::TimeoutSuspendCount()
9930 FORWARD_TO_INNER(TimeoutSuspendCount
, (), 0);
9931 return mTimeoutsSuspendDepth
;
9935 nsGlobalWindow::GetScriptTypeID(PRUint32
*aScriptType
)
9937 NS_ERROR("No default script type here - ask some element");
9938 return nsIProgrammingLanguage::UNKNOWN
;
9942 nsGlobalWindow::SetScriptTypeID(PRUint32 aScriptType
)
9944 NS_ERROR("Can't change default script type for a document");
9945 return NS_ERROR_NOT_IMPLEMENTED
;
9949 nsGlobalWindow::SetHasOrientationEventListener()
9951 mHasAcceleration
= PR_TRUE
;
9952 EnableAccelerationUpdates();
9956 nsGlobalWindow::GetURL(nsIDOMMozURLProperty
** aURL
)
9958 FORWARD_TO_INNER(GetURL
, (aURL
), NS_ERROR_UNEXPECTED
);
9960 if (!mURLProperty
) {
9961 mURLProperty
= new nsDOMMozURLProperty(this);
9964 NS_ADDREF(*aURL
= mURLProperty
);
9969 // nsGlobalChromeWindow implementation
9971 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow
)
9972 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow
,
9974 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mBrowserDOMWindow
)
9975 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMessageManager
)
9976 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
9978 DOMCI_DATA(ChromeWindow
, nsGlobalChromeWindow
)
9980 // QueryInterface implementation for nsGlobalChromeWindow
9981 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsGlobalChromeWindow
)
9982 NS_INTERFACE_MAP_ENTRY(nsIDOMChromeWindow
)
9983 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ChromeWindow
)
9984 NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow
)
9986 NS_IMPL_ADDREF_INHERITED(nsGlobalChromeWindow
, nsGlobalWindow
)
9987 NS_IMPL_RELEASE_INHERITED(nsGlobalChromeWindow
, nsGlobalWindow
)
9990 nsGlobalChromeWindow::GetWindowState(PRUint16
* aWindowState
)
9992 *aWindowState
= nsIDOMChromeWindow::STATE_NORMAL
;
9994 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
9999 nsresult rv
= widget
->GetSizeMode(&aMode
);
10000 NS_ENSURE_SUCCESS(rv
, rv
);
10004 case nsSizeMode_Minimized
:
10005 *aWindowState
= nsIDOMChromeWindow::STATE_MINIMIZED
;
10007 case nsSizeMode_Maximized
:
10008 *aWindowState
= nsIDOMChromeWindow::STATE_MAXIMIZED
;
10010 case nsSizeMode_Fullscreen
:
10011 *aWindowState
= nsIDOMChromeWindow::STATE_FULLSCREEN
;
10013 case nsSizeMode_Normal
:
10014 *aWindowState
= nsIDOMChromeWindow::STATE_NORMAL
;
10017 NS_WARNING("Illegal window state for this chrome window");
10025 nsGlobalChromeWindow::Maximize()
10027 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
10028 nsresult rv
= NS_OK
;
10031 rv
= widget
->SetSizeMode(nsSizeMode_Maximized
);
10038 nsGlobalChromeWindow::Minimize()
10040 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
10041 nsresult rv
= NS_OK
;
10044 rv
= widget
->SetSizeMode(nsSizeMode_Minimized
);
10050 nsGlobalChromeWindow::Restore()
10052 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
10053 nsresult rv
= NS_OK
;
10056 rv
= widget
->SetSizeMode(nsSizeMode_Normal
);
10063 nsGlobalChromeWindow::GetAttention()
10065 return GetAttentionWithCycleCount(-1);
10069 nsGlobalChromeWindow::GetAttentionWithCycleCount(PRInt32 aCycleCount
)
10071 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
10072 nsresult rv
= NS_OK
;
10075 rv
= widget
->GetAttention(aCycleCount
);
10082 nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent
*aMouseDownEvent
)
10084 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
10089 nsCOMPtr
<nsIPrivateDOMEvent
> privEvent
= do_QueryInterface(aMouseDownEvent
);
10090 NS_ENSURE_TRUE(privEvent
, NS_ERROR_FAILURE
);
10091 nsEvent
*internalEvent
= privEvent
->GetInternalNSEvent();
10092 NS_ENSURE_TRUE(internalEvent
&&
10093 internalEvent
->eventStructType
== NS_MOUSE_EVENT
,
10095 nsMouseEvent
*mouseEvent
= static_cast<nsMouseEvent
*>(internalEvent
);
10097 return widget
->BeginMoveDrag(mouseEvent
);
10100 //Note: This call will lock the cursor, it will not change as it moves.
10101 //To unlock, the cursor must be set back to CURSOR_AUTO.
10103 nsGlobalChromeWindow::SetCursor(const nsAString
& aCursor
)
10105 FORWARD_TO_OUTER_CHROME(SetCursor
, (aCursor
), NS_ERROR_NOT_INITIALIZED
);
10107 nsresult rv
= NS_OK
;
10110 // use C strings to keep the code/data size down
10111 NS_ConvertUTF16toUTF8
cursorString(aCursor
);
10113 if (cursorString
.Equals("auto"))
10114 cursor
= NS_STYLE_CURSOR_AUTO
;
10116 nsCSSKeyword keyword
= nsCSSKeywords::LookupKeyword(aCursor
);
10117 if (eCSSKeyword_UNKNOWN
== keyword
||
10118 !nsCSSProps::FindKeyword(keyword
, nsCSSProps::kCursorKTable
, cursor
)) {
10119 // XXX remove the following three values (leave return NS_OK) after 1.8
10120 // XXX since they should have been -moz- prefixed (covered by FindKeyword).
10121 // XXX (also remove |cursorString| at that point?).
10122 if (cursorString
.Equals("grab"))
10123 cursor
= NS_STYLE_CURSOR_GRAB
;
10124 else if (cursorString
.Equals("grabbing"))
10125 cursor
= NS_STYLE_CURSOR_GRABBING
;
10126 else if (cursorString
.Equals("spinning"))
10127 cursor
= NS_STYLE_CURSOR_SPINNING
;
10133 nsRefPtr
<nsPresContext
> presContext
;
10135 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
10139 // Need root widget.
10140 nsCOMPtr
<nsIPresShell
> presShell
;
10141 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
10142 NS_ENSURE_TRUE(presShell
, NS_ERROR_FAILURE
);
10144 nsIViewManager
* vm
= presShell
->GetViewManager();
10145 NS_ENSURE_TRUE(vm
, NS_ERROR_FAILURE
);
10148 vm
->GetRootView(rootView
);
10149 NS_ENSURE_TRUE(rootView
, NS_ERROR_FAILURE
);
10151 nsIWidget
* widget
= rootView
->GetNearestWidget(nsnull
);
10152 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
10154 // Call esm and set cursor.
10155 rv
= presContext
->EventStateManager()->SetCursor(cursor
, nsnull
,
10156 PR_FALSE
, 0.0f
, 0.0f
,
10164 nsGlobalChromeWindow::GetBrowserDOMWindow(nsIBrowserDOMWindow
**aBrowserWindow
)
10166 FORWARD_TO_OUTER_CHROME(GetBrowserDOMWindow
, (aBrowserWindow
),
10167 NS_ERROR_NOT_INITIALIZED
);
10169 NS_ENSURE_ARG_POINTER(aBrowserWindow
);
10171 *aBrowserWindow
= mBrowserDOMWindow
;
10172 NS_IF_ADDREF(*aBrowserWindow
);
10177 nsGlobalChromeWindow::SetBrowserDOMWindow(nsIBrowserDOMWindow
*aBrowserWindow
)
10179 FORWARD_TO_OUTER_CHROME(SetBrowserDOMWindow
, (aBrowserWindow
),
10180 NS_ERROR_NOT_INITIALIZED
);
10182 mBrowserDOMWindow
= aBrowserWindow
;
10187 nsGlobalChromeWindow::NotifyDefaultButtonLoaded(nsIDOMElement
* aDefaultButton
)
10190 NS_ENSURE_ARG(aDefaultButton
);
10192 // Don't snap to a disabled button.
10193 nsCOMPtr
<nsIDOMXULControlElement
> xulControl
=
10194 do_QueryInterface(aDefaultButton
);
10195 NS_ENSURE_TRUE(xulControl
, NS_ERROR_FAILURE
);
10197 nsresult rv
= xulControl
->GetDisabled(&disabled
);
10198 NS_ENSURE_SUCCESS(rv
, rv
);
10202 // Get the button rect in screen coordinates.
10203 nsCOMPtr
<nsIContent
> content(do_QueryInterface(aDefaultButton
));
10204 NS_ENSURE_TRUE(content
, NS_ERROR_FAILURE
);
10205 nsIFrame
*frame
= content
->GetPrimaryFrame();
10206 NS_ENSURE_TRUE(frame
, NS_ERROR_FAILURE
);
10207 nsIntRect buttonRect
= frame
->GetScreenRect();
10209 // Get the widget rect in screen coordinates.
10210 nsIWidget
*widget
= GetNearestWidget();
10211 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
10212 nsIntRect widgetRect
;
10213 rv
= widget
->GetScreenBounds(widgetRect
);
10214 NS_ENSURE_SUCCESS(rv
, rv
);
10216 // Convert the buttonRect coordinates from screen to the widget.
10217 buttonRect
-= widgetRect
.TopLeft();
10218 rv
= widget
->OnDefaultButtonLoaded(buttonRect
);
10219 if (rv
== NS_ERROR_NOT_IMPLEMENTED
)
10223 return NS_ERROR_NOT_IMPLEMENTED
;
10228 nsGlobalChromeWindow::GetMessageManager(nsIChromeFrameMessageManager
** aManager
)
10230 FORWARD_TO_INNER_CHROME(GetMessageManager
, (aManager
), NS_ERROR_FAILURE
);
10231 if (!mMessageManager
) {
10232 nsIScriptContext
* scx
= GetContextInternal();
10233 NS_ENSURE_STATE(scx
);
10234 JSContext
* cx
= (JSContext
*)scx
->GetNativeContext();
10235 NS_ENSURE_STATE(cx
);
10236 nsCOMPtr
<nsIChromeFrameMessageManager
> globalMM
=
10237 do_GetService("@mozilla.org/globalmessagemanager;1");
10239 new nsFrameMessageManager(PR_TRUE
,
10244 static_cast<nsFrameMessageManager
*>(globalMM
.get()),
10246 NS_ENSURE_TRUE(mMessageManager
, NS_ERROR_OUT_OF_MEMORY
);
10248 CallQueryInterface(mMessageManager
, aManager
);
10252 // nsGlobalModalWindow implementation
10254 // QueryInterface implementation for nsGlobalModalWindow
10255 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalModalWindow
)
10256 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalModalWindow
,
10258 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mReturnValue
)
10259 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
10261 DOMCI_DATA(ModalContentWindow
, nsGlobalModalWindow
)
10263 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsGlobalModalWindow
)
10264 NS_INTERFACE_MAP_ENTRY(nsIDOMModalContentWindow
)
10265 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ModalContentWindow
)
10266 NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow
)
10268 NS_IMPL_ADDREF_INHERITED(nsGlobalModalWindow
, nsGlobalWindow
)
10269 NS_IMPL_RELEASE_INHERITED(nsGlobalModalWindow
, nsGlobalWindow
)
10272 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGlobalModalWindow
,
10274 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mReturnValue
)
10275 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
10279 nsGlobalModalWindow::GetDialogArguments(nsIArray
**aArguments
)
10281 FORWARD_TO_INNER_MODAL_CONTENT_WINDOW(GetDialogArguments
, (aArguments
),
10282 NS_ERROR_NOT_INITIALIZED
);
10284 PRBool subsumes
= PR_FALSE
;
10285 nsIPrincipal
*self
= GetPrincipal();
10286 if (self
&& NS_SUCCEEDED(self
->Subsumes(mArgumentsOrigin
, &subsumes
)) &&
10288 NS_IF_ADDREF(*aArguments
= mArguments
);
10290 *aArguments
= nsnull
;
10297 nsGlobalModalWindow::GetReturnValue(nsIVariant
**aRetVal
)
10299 FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(GetReturnValue
, (aRetVal
), NS_OK
);
10301 NS_IF_ADDREF(*aRetVal
= mReturnValue
);
10307 nsGlobalModalWindow::SetReturnValue(nsIVariant
*aRetVal
)
10309 FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(SetReturnValue
, (aRetVal
), NS_OK
);
10311 mReturnValue
= aRetVal
;
10317 nsGlobalModalWindow::SetNewDocument(nsIDocument
*aDocument
,
10318 nsISupports
*aState
,
10319 PRBool aForceReuseInnerWindow
)
10321 // If we're loading a new document into a modal dialog, clear the
10322 // return value that was set, if any, by the current document.
10324 mReturnValue
= nsnull
;
10327 return nsGlobalWindow::SetNewDocument(aDocument
, aState
,
10328 aForceReuseInnerWindow
);
10331 //*****************************************************************************
10332 // nsGlobalWindow: Creator Function (This should go away)
10333 //*****************************************************************************
10336 NS_NewScriptGlobalObject(PRBool aIsChrome
, PRBool aIsModalContentWindow
,
10337 nsIScriptGlobalObject
**aResult
)
10341 nsGlobalWindow
*global
;
10344 global
= new nsGlobalChromeWindow(nsnull
);
10345 } else if (aIsModalContentWindow
) {
10346 global
= new nsGlobalModalWindow(nsnull
);
10348 global
= new nsGlobalWindow(nsnull
);
10351 NS_ENSURE_TRUE(global
, NS_ERROR_OUT_OF_MEMORY
);
10353 NS_ADDREF(*aResult
= global
);
10358 //*****************************************************************************
10359 //*** nsNavigator: Object Management
10360 //*****************************************************************************
10362 nsNavigator::nsNavigator(nsIDocShell
*aDocShell
)
10363 : mDocShell(aDocShell
)
10367 nsNavigator::~nsNavigator()
10370 mMimeTypes
->Invalidate();
10372 mPlugins
->Invalidate();
10375 //*****************************************************************************
10376 // nsNavigator::nsISupports
10377 //*****************************************************************************
10380 DOMCI_DATA(Navigator
, nsNavigator
)
10382 // QueryInterface implementation for nsNavigator
10383 NS_INTERFACE_MAP_BEGIN(nsNavigator
)
10384 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMNavigator
)
10385 NS_INTERFACE_MAP_ENTRY(nsIDOMNavigator
)
10386 NS_INTERFACE_MAP_ENTRY(nsIDOMClientInformation
)
10387 NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorGeolocation
)
10388 NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorDesktopNotification
)
10389 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Navigator
)
10390 NS_INTERFACE_MAP_END
10393 NS_IMPL_ADDREF(nsNavigator
)
10394 NS_IMPL_RELEASE(nsNavigator
)
10398 nsNavigator::SetDocShell(nsIDocShell
*aDocShell
)
10400 mDocShell
= aDocShell
;
10402 mPlugins
->SetDocShell(aDocShell
);
10404 // if there is a page transition, make sure delete the geolocation object
10407 mGeolocation
->Shutdown();
10408 mGeolocation
= nsnull
;
10413 mNotification
->Shutdown();
10414 mNotification
= nsnull
;
10418 //*****************************************************************************
10419 // nsNavigator::nsIDOMNavigator
10420 //*****************************************************************************
10423 NS_GetNavigatorUserAgent(nsAString
& aUserAgent
)
10426 nsCOMPtr
<nsIHttpProtocolHandler
>
10427 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10428 if (NS_SUCCEEDED(rv
)) {
10430 rv
= service
->GetUserAgent(ua
);
10431 CopyASCIItoUTF16(ua
, aUserAgent
);
10438 NS_GetNavigatorPlatform(nsAString
& aPlatform
)
10440 if (!nsContentUtils::IsCallerTrustedForRead()) {
10441 const nsAdoptingCString
& override
=
10442 nsContentUtils::GetCharPref("general.platform.override");
10445 CopyUTF8toUTF16(override
, aPlatform
);
10451 nsCOMPtr
<nsIHttpProtocolHandler
>
10452 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10453 if (NS_SUCCEEDED(rv
)) {
10454 // sorry for the #if platform ugliness, but Communicator is
10455 // likewise hardcoded and we're seeking backward compatibility
10456 // here (bug 47080)
10457 #if defined(_WIN64)
10458 aPlatform
.AssignLiteral("Win64");
10459 #elif defined(WIN32)
10460 aPlatform
.AssignLiteral("Win32");
10461 #elif defined(XP_MACOSX) && defined(__ppc__)
10462 aPlatform
.AssignLiteral("MacPPC");
10463 #elif defined(XP_MACOSX) && defined(__i386__)
10464 aPlatform
.AssignLiteral("MacIntel");
10465 #elif defined(XP_MACOSX) && defined(__x86_64__)
10466 aPlatform
.AssignLiteral("MacIntel");
10467 #elif defined(XP_OS2)
10468 aPlatform
.AssignLiteral("OS/2");
10470 // XXX Communicator uses compiled-in build-time string defines
10471 // to indicate the platform it was compiled *for*, not what it is
10472 // currently running *on* which is what this does.
10473 nsCAutoString plat
;
10474 rv
= service
->GetOscpu(plat
);
10475 CopyASCIItoUTF16(plat
, aPlatform
);
10482 NS_GetNavigatorAppVersion(nsAString
& aAppVersion
)
10484 if (!nsContentUtils::IsCallerTrustedForRead()) {
10485 const nsAdoptingCString
& override
=
10486 nsContentUtils::GetCharPref("general.appversion.override");
10489 CopyUTF8toUTF16(override
, aAppVersion
);
10495 nsCOMPtr
<nsIHttpProtocolHandler
>
10496 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10497 if (NS_SUCCEEDED(rv
)) {
10499 rv
= service
->GetAppVersion(str
);
10500 CopyASCIItoUTF16(str
, aAppVersion
);
10504 aAppVersion
.AppendLiteral(" (");
10506 rv
= service
->GetPlatform(str
);
10510 AppendASCIItoUTF16(str
, aAppVersion
);
10512 aAppVersion
.Append(PRUnichar(')'));
10519 NS_GetNavigatorAppName(nsAString
& aAppName
)
10521 if (!nsContentUtils::IsCallerTrustedForRead()) {
10522 const nsAdoptingCString
& override
=
10523 nsContentUtils::GetCharPref("general.appname.override");
10526 CopyUTF8toUTF16(override
, aAppName
);
10531 aAppName
.AssignLiteral("Netscape");
10536 nsNavigator::GetUserAgent(nsAString
& aUserAgent
)
10538 return NS_GetNavigatorUserAgent(aUserAgent
);
10542 nsNavigator::GetAppCodeName(nsAString
& aAppCodeName
)
10545 nsCOMPtr
<nsIHttpProtocolHandler
>
10546 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10547 if (NS_SUCCEEDED(rv
)) {
10548 nsCAutoString appName
;
10549 rv
= service
->GetAppName(appName
);
10550 CopyASCIItoUTF16(appName
, aAppCodeName
);
10557 nsNavigator::GetAppVersion(nsAString
& aAppVersion
)
10559 return NS_GetNavigatorAppVersion(aAppVersion
);
10563 nsNavigator::GetAppName(nsAString
& aAppName
)
10565 return NS_GetNavigatorAppName(aAppName
);
10569 nsNavigator::GetLanguage(nsAString
& aLanguage
)
10572 nsCOMPtr
<nsIHttpProtocolHandler
>
10573 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10574 if (NS_SUCCEEDED(rv
)) {
10575 nsCAutoString lang
;
10576 rv
= service
->GetLanguage(lang
);
10577 CopyASCIItoUTF16(lang
, aLanguage
);
10584 nsNavigator::GetPlatform(nsAString
& aPlatform
)
10586 return NS_GetNavigatorPlatform(aPlatform
);
10590 nsNavigator::GetOscpu(nsAString
& aOSCPU
)
10592 if (!nsContentUtils::IsCallerTrustedForRead()) {
10593 const nsAdoptingCString
& override
=
10594 nsContentUtils::GetCharPref("general.oscpu.override");
10597 CopyUTF8toUTF16(override
, aOSCPU
);
10603 nsCOMPtr
<nsIHttpProtocolHandler
>
10604 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10605 if (NS_SUCCEEDED(rv
)) {
10606 nsCAutoString oscpu
;
10607 rv
= service
->GetOscpu(oscpu
);
10608 CopyASCIItoUTF16(oscpu
, aOSCPU
);
10615 nsNavigator::GetVendor(nsAString
& aVendor
)
10617 aVendor
.Truncate();
10623 nsNavigator::GetVendorSub(nsAString
& aVendorSub
)
10625 aVendorSub
.Truncate();
10630 nsNavigator::GetProduct(nsAString
& aProduct
)
10633 nsCOMPtr
<nsIHttpProtocolHandler
>
10634 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10635 if (NS_SUCCEEDED(rv
)) {
10636 nsCAutoString product
;
10637 rv
= service
->GetProduct(product
);
10638 CopyASCIItoUTF16(product
, aProduct
);
10645 nsNavigator::GetProductSub(nsAString
& aProductSub
)
10647 if (!nsContentUtils::IsCallerTrustedForRead()) {
10648 const nsAdoptingCString
& override
=
10649 nsContentUtils::GetCharPref("general.productSub.override");
10652 CopyUTF8toUTF16(override
, aProductSub
);
10655 // 'general.useragent.productSub' backwards compatible with 1.8 branch.
10656 const nsAdoptingCString
& override2
=
10657 nsContentUtils::GetCharPref("general.useragent.productSub");
10660 CopyUTF8toUTF16(override2
, aProductSub
);
10667 nsCOMPtr
<nsIHttpProtocolHandler
>
10668 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10669 if (NS_SUCCEEDED(rv
)) {
10670 nsCAutoString productSub
;
10671 rv
= service
->GetProductSub(productSub
);
10672 CopyASCIItoUTF16(productSub
, aProductSub
);
10679 nsNavigator::GetSecurityPolicy(nsAString
& aSecurityPolicy
)
10685 nsNavigator::GetMimeTypes(nsIDOMMimeTypeArray
**aMimeTypes
)
10688 mMimeTypes
= new nsMimeTypeArray(this);
10690 return NS_ERROR_OUT_OF_MEMORY
;
10694 NS_ADDREF(*aMimeTypes
= mMimeTypes
);
10700 nsNavigator::GetPlugins(nsIDOMPluginArray
**aPlugins
)
10703 mPlugins
= new nsPluginArray(this, mDocShell
);
10705 return NS_ERROR_OUT_OF_MEMORY
;
10709 NS_ADDREF(*aPlugins
= mPlugins
);
10714 // values for the network.cookie.cookieBehavior pref are documented in
10715 // nsCookieService.cpp.
10716 #define COOKIE_BEHAVIOR_REJECT 2
10719 nsNavigator::GetCookieEnabled(PRBool
*aCookieEnabled
)
10722 (nsContentUtils::GetIntPref("network.cookie.cookieBehavior",
10723 COOKIE_BEHAVIOR_REJECT
) !=
10724 COOKIE_BEHAVIOR_REJECT
);
10730 nsNavigator::GetOnLine(PRBool
* aOnline
)
10732 NS_PRECONDITION(aOnline
, "Null out param");
10734 *aOnline
= !NS_IsOffline();
10739 nsNavigator::GetBuildID(nsAString
& aBuildID
)
10741 if (!nsContentUtils::IsCallerTrustedForRead()) {
10742 const nsAdoptingCString
& override
=
10743 nsContentUtils::GetCharPref("general.buildID.override");
10746 CopyUTF8toUTF16(override
, aBuildID
);
10751 nsCOMPtr
<nsIXULAppInfo
> appInfo
=
10752 do_GetService("@mozilla.org/xre/app-info;1");
10754 return NS_ERROR_NOT_IMPLEMENTED
;
10756 nsCAutoString buildID
;
10757 nsresult rv
= appInfo
->GetAppBuildID(buildID
);
10761 aBuildID
.Truncate();
10762 AppendASCIItoUTF16(buildID
, aBuildID
);
10767 nsNavigator::JavaEnabled(PRBool
*aReturn
)
10769 // Return true if we have a handler for "application/x-java-vm",
10770 // otherwise return false.
10771 *aReturn
= PR_FALSE
;
10774 mMimeTypes
= new nsMimeTypeArray(this);
10776 return NS_ERROR_OUT_OF_MEMORY
;
10779 RefreshMIMEArray();
10782 mMimeTypes
->GetLength(&count
);
10783 for (PRUint32 i
= 0; i
< count
; i
++) {
10785 nsIDOMMimeType
* type
= mMimeTypes
->GetItemAt(i
, &rv
);
10786 nsAutoString mimeString
;
10787 if (type
&& NS_SUCCEEDED(type
->GetType(mimeString
))) {
10788 if (mimeString
.EqualsLiteral("application/x-java-vm")) {
10789 *aReturn
= PR_TRUE
;
10799 nsNavigator::TaintEnabled(PRBool
*aReturn
)
10801 *aReturn
= PR_FALSE
;
10806 nsNavigator::LoadingNewDocument()
10808 // Release these so that they will be recreated for the
10809 // new document (if requested). The plugins or mime types
10810 // arrays may have changed. See bug 150087.
10812 mMimeTypes
->Invalidate();
10813 mMimeTypes
= nsnull
;
10817 mPlugins
->Invalidate();
10823 mGeolocation
->Shutdown();
10824 mGeolocation
= nsnull
;
10829 mNotification
->Shutdown();
10830 mNotification
= nsnull
;
10836 nsNavigator::RefreshMIMEArray()
10838 nsresult rv
= NS_OK
;
10840 rv
= mMimeTypes
->Refresh();
10845 nsNavigator::HasDesktopNotificationSupport()
10847 return nsContentUtils::GetBoolPref("notification.feature.enabled", PR_FALSE
);
10850 //*****************************************************************************
10851 // nsNavigator::nsIDOMClientInformation
10852 //*****************************************************************************
10855 nsNavigator::RegisterContentHandler(const nsAString
& aMIMEType
,
10856 const nsAString
& aURI
,
10857 const nsAString
& aTitle
)
10859 nsCOMPtr
<nsIWebContentHandlerRegistrar
> registrar
=
10860 do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID
);
10861 if (registrar
&& mDocShell
) {
10862 nsCOMPtr
<nsIDOMWindow
> contentDOMWindow(do_GetInterface(mDocShell
));
10863 if (contentDOMWindow
)
10864 return registrar
->RegisterContentHandler(aMIMEType
, aURI
, aTitle
,
10872 nsNavigator::RegisterProtocolHandler(const nsAString
& aProtocol
,
10873 const nsAString
& aURI
,
10874 const nsAString
& aTitle
)
10876 nsCOMPtr
<nsIWebContentHandlerRegistrar
> registrar
=
10877 do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID
);
10878 if (registrar
&& mDocShell
) {
10879 nsCOMPtr
<nsIDOMWindow
> contentDOMWindow(do_GetInterface(mDocShell
));
10880 if (contentDOMWindow
)
10881 return registrar
->RegisterProtocolHandler(aProtocol
, aURI
, aTitle
,
10890 nsNavigator::MozIsLocallyAvailable(const nsAString
&aURI
,
10891 PRBool aWhenOffline
,
10892 PRBool
*aIsAvailable
)
10894 nsCOMPtr
<nsIURI
> uri
;
10895 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aURI
);
10896 NS_ENSURE_SUCCESS(rv
, rv
);
10898 // This method of checking the cache will only work for http/https urls
10900 rv
= uri
->SchemeIs("http", &match
);
10901 NS_ENSURE_SUCCESS(rv
, rv
);
10903 rv
= uri
->SchemeIs("https", &match
);
10904 NS_ENSURE_SUCCESS(rv
, rv
);
10905 if (!match
) return NS_ERROR_DOM_BAD_URI
;
10908 // Same origin check
10909 nsCOMPtr
<nsIJSContextStack
> stack
= do_GetService(sJSStackContractID
);
10910 NS_ENSURE_TRUE(stack
, NS_ERROR_FAILURE
);
10912 JSContext
*cx
= nsnull
;
10913 rv
= stack
->Peek(&cx
);
10914 NS_ENSURE_TRUE(cx
, NS_ERROR_FAILURE
);
10916 rv
= nsContentUtils::GetSecurityManager()->CheckSameOrigin(cx
, uri
);
10917 NS_ENSURE_SUCCESS(rv
, rv
);
10919 // these load flags cause an error to be thrown if there is no
10920 // valid cache entry, and skip the load if there is.
10921 // if the cache is busy, assume that it is not yet available rather
10922 // than waiting for it to become available.
10923 PRUint32 loadFlags
= nsIChannel::INHIBIT_CACHING
|
10924 nsICachingChannel::LOAD_NO_NETWORK_IO
|
10925 nsICachingChannel::LOAD_ONLY_IF_MODIFIED
|
10926 nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY
;
10928 if (aWhenOffline
) {
10929 loadFlags
|= nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE
|
10930 nsICachingChannel::LOAD_ONLY_FROM_CACHE
|
10931 nsIRequest::LOAD_FROM_CACHE
;
10934 nsCOMPtr
<nsIChannel
> channel
;
10935 rv
= NS_NewChannel(getter_AddRefs(channel
), uri
,
10936 nsnull
, nsnull
, nsnull
, loadFlags
);
10937 NS_ENSURE_SUCCESS(rv
, rv
);
10939 nsCOMPtr
<nsIInputStream
> stream
;
10940 rv
= channel
->Open(getter_AddRefs(stream
));
10941 NS_ENSURE_SUCCESS(rv
, rv
);
10946 rv
= channel
->GetStatus(&status
);
10947 NS_ENSURE_SUCCESS(rv
, rv
);
10949 if (NS_SUCCEEDED(status
)) {
10950 nsCOMPtr
<nsIHttpChannel
> httpChannel
= do_QueryInterface(channel
);
10951 rv
= httpChannel
->GetRequestSucceeded(aIsAvailable
);
10952 NS_ENSURE_SUCCESS(rv
, rv
);
10954 *aIsAvailable
= PR_FALSE
;
10960 //*****************************************************************************
10961 // nsNavigator::nsIDOMNavigatorGeolocation
10962 //*****************************************************************************
10964 NS_IMETHODIMP
nsNavigator::GetGeolocation(nsIDOMGeoGeolocation
**_retval
)
10966 NS_ENSURE_ARG_POINTER(_retval
);
10969 if (mGeolocation
) {
10970 NS_ADDREF(*_retval
= mGeolocation
);
10975 return NS_ERROR_FAILURE
;
10977 nsCOMPtr
<nsIDOMWindow
> contentDOMWindow(do_GetInterface(mDocShell
));
10978 if (!contentDOMWindow
)
10979 return NS_ERROR_FAILURE
;
10981 mGeolocation
= new nsGeolocation();
10983 return NS_ERROR_FAILURE
;
10985 if (NS_FAILED(mGeolocation
->Init(contentDOMWindow
)))
10986 return NS_ERROR_FAILURE
;
10988 NS_ADDREF(*_retval
= mGeolocation
);
10993 //*****************************************************************************
10994 // nsNavigator::nsIDOMNavigatorDesktopNotification
10995 //*****************************************************************************
10997 NS_IMETHODIMP
nsNavigator::GetMozNotification(nsIDOMDesktopNotificationCenter
**aRetVal
)
10999 NS_ENSURE_ARG_POINTER(aRetVal
);
11002 if (mNotification
) {
11003 NS_ADDREF(*aRetVal
= mNotification
);
11007 nsCOMPtr
<nsPIDOMWindow
> window(do_GetInterface(mDocShell
));
11008 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
11010 nsCOMPtr
<nsIDocument
> document
= do_GetInterface(mDocShell
);
11011 NS_ENSURE_TRUE(document
, NS_ERROR_FAILURE
);
11013 nsIScriptGlobalObject
*sgo
= document
->GetScopeObject();
11014 NS_ENSURE_TRUE(sgo
, NS_ERROR_FAILURE
);
11016 nsIScriptContext
*scx
= sgo
->GetContext();
11017 NS_ENSURE_TRUE(scx
, NS_ERROR_FAILURE
);
11019 mNotification
= new nsDesktopNotificationCenter(window
->GetCurrentInnerWindow(),
11021 if (!mNotification
) {
11022 return NS_ERROR_FAILURE
;
11025 NS_ADDREF(*aRetVal
= mNotification
);