1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 sw=2 et tw=80: */
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 1998
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Travis Bogard <travis@netscape.com>
25 : * Dan Rosen <dr@netscape.com>
26 : * Vidur Apparao <vidur@netscape.com>
27 : * Johnny Stenback <jst@netscape.com>
28 : *
29 : * Alternatively, the contents of this file may be used under the terms of
30 : * either of the GNU General Public License Version 2 or later (the "GPL"),
31 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
32 : * in which case the provisions of the GPL or the LGPL are applicable instead
33 : * of those above. If you wish to allow use of your version of this file only
34 : * under the terms of either the GPL or the LGPL, and not to allow others to
35 : * use your version of this file under the terms of the MPL, indicate your
36 : * decision by deleting the provisions above and replace them with the notice
37 : * and other provisions required by the GPL or the LGPL. If you do not delete
38 : * the provisions above, a recipient may use your version of this file under
39 : * the terms of any one of the MPL, the GPL or the LGPL.
40 : *
41 : * ***** END LICENSE BLOCK ***** */
42 :
43 : #ifndef nsGlobalWindow_h___
44 : #define nsGlobalWindow_h___
45 :
46 : #include "mozilla/XPCOM.h" // for TimeStamp/TimeDuration
47 :
48 : // Local Includes
49 : // Helper Classes
50 : #include "nsCOMPtr.h"
51 : #include "nsAutoPtr.h"
52 : #include "nsWeakReference.h"
53 : #include "nsHashtable.h"
54 : #include "nsDataHashtable.h"
55 : #include "nsCycleCollectionParticipant.h"
56 : #include "nsDOMScriptObjectHolder.h"
57 :
58 : // Interfaces Needed
59 : #include "nsDOMWindowList.h"
60 : #include "nsIBaseWindow.h"
61 : #include "nsIBrowserDOMWindow.h"
62 : #include "nsIDocShellTreeOwner.h"
63 : #include "nsIDocShellTreeItem.h"
64 : #include "nsIDOMEventTarget.h"
65 : #include "nsIInterfaceRequestor.h"
66 : #include "nsIInterfaceRequestorUtils.h"
67 : #include "nsIDOMJSWindow.h"
68 : #include "nsIDOMChromeWindow.h"
69 : #include "nsIScriptGlobalObject.h"
70 : #include "nsIScriptContext.h"
71 : #include "nsIScriptObjectPrincipal.h"
72 : #include "nsIScriptTimeoutHandler.h"
73 : #include "nsITimer.h"
74 : #include "nsIWebBrowserChrome.h"
75 : #include "nsPIDOMWindow.h"
76 : #include "nsIDOMModalContentWindow.h"
77 : #include "nsIScriptSecurityManager.h"
78 : #include "nsEventListenerManager.h"
79 : #include "nsIDOMDocument.h"
80 : #ifndef MOZ_DISABLE_DOMCRYPTO
81 : #include "nsIDOMCrypto.h"
82 : #endif
83 : #include "nsIPrincipal.h"
84 : #include "nsIXPCScriptable.h"
85 : #include "nsPoint.h"
86 : #include "nsSize.h"
87 : #include "nsRect.h"
88 : #include "mozFlushType.h"
89 : #include "prclist.h"
90 : #include "nsIDOMStorageObsolete.h"
91 : #include "nsIDOMStorageList.h"
92 : #include "nsIDOMStorageEvent.h"
93 : #include "nsIDOMStorageIndexedDB.h"
94 : #include "nsIDOMOfflineResourceList.h"
95 : #include "nsIArray.h"
96 : #include "nsIContent.h"
97 : #include "nsIIDBFactory.h"
98 : #include "nsFrameMessageManager.h"
99 : #include "mozilla/TimeStamp.h"
100 : #include "nsIDOMTouchEvent.h"
101 : #include "nsIInlineEventHandlers.h"
102 :
103 : // JS includes
104 : #include "jsapi.h"
105 : #include "jswrapper.h"
106 :
107 : #define DEFAULT_HOME_PAGE "www.mozilla.org"
108 : #define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage"
109 :
110 : // Amount of time allowed between alert/prompt/confirm before enabling
111 : // the stop dialog checkbox.
112 : #define SUCCESSIVE_DIALOG_TIME_LIMIT 3 // 3 sec
113 :
114 : // During click or mousedown events (and others, see nsDOMEvent) we allow modal
115 : // dialogs up to this limit, even if they were disabled.
116 : #define MAX_DIALOG_COUNT 10
117 :
118 : class nsIDOMBarProp;
119 : class nsIDocument;
120 : class nsPresContext;
121 : class nsIDOMEvent;
122 : class nsIScrollableFrame;
123 : class nsIControllers;
124 :
125 : class nsBarProp;
126 : class nsLocation;
127 : class nsScreen;
128 : class nsHistory;
129 : class nsPerformance;
130 : class nsIDocShellLoadInfo;
131 : class WindowStateHolder;
132 : class nsGlobalWindowObserver;
133 : class nsGlobalWindow;
134 : class nsDummyJavaPluginOwner;
135 : class PostMessageEvent;
136 : class nsRunnable;
137 : class nsDOMEventTargetHelper;
138 : class nsDOMOfflineResourceList;
139 : class nsDOMMozURLProperty;
140 :
141 : #ifdef MOZ_DISABLE_DOMCRYPTO
142 : class nsIDOMCrypto;
143 : #endif
144 :
145 : class nsWindowSizes;
146 :
147 : namespace mozilla {
148 : namespace dom {
149 : class Navigator;
150 : } // namespace dom
151 : } // namespace mozilla
152 :
153 : extern nsresult
154 : NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow,
155 : bool *aIsInterval,
156 : PRInt32 *aInterval,
157 : nsIScriptTimeoutHandler **aRet);
158 :
159 : /*
160 : * Timeout struct that holds information about each script
161 : * timeout. Holds a strong reference to an nsIScriptTimeoutHandler, which
162 : * abstracts the language specific cruft.
163 : */
164 : struct nsTimeout : PRCList
165 : {
166 : nsTimeout();
167 : ~nsTimeout();
168 :
169 1464 : NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsTimeout)
170 :
171 : nsrefcnt Release();
172 : nsrefcnt AddRef();
173 :
174 0 : nsTimeout* Next() {
175 : // Note: might not actually return an nsTimeout. Use IsTimeout to check.
176 0 : return static_cast<nsTimeout*>(PR_NEXT_LINK(this));
177 : }
178 :
179 0 : nsTimeout* Prev() {
180 : // Note: might not actually return an nsTimeout. Use IsTimeout to check.
181 0 : return static_cast<nsTimeout*>(PR_PREV_LINK(this));
182 : }
183 :
184 : // Window for which this timeout fires
185 : nsRefPtr<nsGlobalWindow> mWindow;
186 :
187 : // The actual timer object
188 : nsCOMPtr<nsITimer> mTimer;
189 :
190 : // True if the timeout was cleared
191 : bool mCleared;
192 :
193 : // True if this is one of the timeouts that are currently running
194 : bool mRunning;
195 :
196 : // True if this is a repeating/interval timer
197 : bool mIsInterval;
198 :
199 : // Returned as value of setTimeout()
200 : PRUint32 mPublicId;
201 :
202 : // Interval in milliseconds
203 : PRUint32 mInterval;
204 :
205 : // mWhen and mTimeRemaining can't be in a union, sadly, because they
206 : // have constructors.
207 : // Nominal time to run this timeout. Use only when timeouts are not
208 : // suspended.
209 : mozilla::TimeStamp mWhen;
210 : // Remaining time to wait. Used only when timeouts are suspended.
211 : mozilla::TimeDuration mTimeRemaining;
212 :
213 : // Principal with which to execute
214 : nsCOMPtr<nsIPrincipal> mPrincipal;
215 :
216 : // stack depth at which timeout is firing
217 : PRUint32 mFiringDepth;
218 :
219 : //
220 : PRUint32 mNestingLevel;
221 :
222 : // The popup state at timeout creation time if not created from
223 : // another timeout
224 : PopupControlState mPopupState;
225 :
226 : // The language-specific information about the callback.
227 : nsCOMPtr<nsIScriptTimeoutHandler> mScriptHandler;
228 :
229 : private:
230 : // reference count for shared usage
231 : nsAutoRefCnt mRefCnt;
232 : };
233 :
234 : //*****************************************************************************
235 : // nsOuterWindow: Outer Window Proxy
236 : //*****************************************************************************
237 :
238 : class nsOuterWindowProxy : public js::Wrapper
239 2974 : {
240 : public:
241 1464 : nsOuterWindowProxy() : js::Wrapper((unsigned)0) {}
242 :
243 0 : virtual bool isOuterWindow() {
244 0 : return true;
245 : }
246 : JSString *obj_toString(JSContext *cx, JSObject *wrapper);
247 : void finalize(JSContext *cx, JSObject *proxy);
248 :
249 : static nsOuterWindowProxy singleton;
250 : };
251 :
252 : JSObject *NS_NewOuterWindowProxy(JSContext *cx, JSObject *parent);
253 :
254 : //*****************************************************************************
255 : // nsGlobalWindow: Global Object for Scripting
256 : //*****************************************************************************
257 : // Beware that all scriptable interfaces implemented by
258 : // nsGlobalWindow will be reachable from JS, if you make this class
259 : // implement new interfaces you better know what you're
260 : // doing. Security wise this is very sensitive code. --
261 : // jst@netscape.com
262 :
263 : // nsGlobalWindow inherits PRCList for maintaining a list of all inner
264 : // windows still in memory for any given outer window. This list is
265 : // needed to ensure that mOuterWindow doesn't end up dangling. The
266 : // nature of PRCList means that the window itself is always in the
267 : // list, and an outer window's list will also contain all inner window
268 : // objects that are still in memory (and in reality all inner window
269 : // object's lists also contain its outer and all other inner windows
270 : // belonging to the same outer window, but that's an unimportant
271 : // side effect of inheriting PRCList).
272 :
273 : class nsGlobalWindow : public nsPIDOMWindow,
274 : public nsIScriptGlobalObject,
275 : public nsIDOMJSWindow,
276 : public nsIScriptObjectPrincipal,
277 : public nsIDOMEventTarget,
278 : public nsIDOMStorageIndexedDB,
279 : public nsSupportsWeakReference,
280 : public nsIInterfaceRequestor,
281 : public nsWrapperCache,
282 : public PRCListStr,
283 : public nsIDOMWindowPerformance,
284 : public nsITouchEventReceiver,
285 : public nsIInlineEventHandlers
286 : {
287 : public:
288 : friend class nsDOMMozURLProperty;
289 :
290 : typedef mozilla::TimeStamp TimeStamp;
291 : typedef mozilla::TimeDuration TimeDuration;
292 : typedef mozilla::dom::Navigator Navigator;
293 : typedef nsDataHashtable<nsUint64HashKey, nsGlobalWindow*> WindowByIdTable;
294 :
295 : // public methods
296 : nsPIDOMWindow* GetPrivateParent();
297 : // callback for close event
298 : void ReallyCloseWindow();
299 :
300 : // nsISupports
301 0 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
302 :
303 : // nsWrapperCache
304 0 : JSObject *WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
305 : bool *triedToWrap)
306 : {
307 0 : NS_ASSERTION(IsOuterWindow(),
308 : "Inner window supports nsWrapperCache, fix WrapObject!");
309 0 : *triedToWrap = true;
310 0 : return EnsureInnerWindow() ? GetWrapper() : nsnull;
311 : }
312 :
313 : // nsIScriptGlobalObject
314 : virtual nsIScriptContext *GetContext();
315 : virtual JSObject *GetGlobalJSObject();
316 0 : JSObject *FastGetGlobalJSObject()
317 : {
318 0 : return mJSObject;
319 : }
320 :
321 : virtual nsresult EnsureScriptEnvironment(PRUint32 aLangID);
322 :
323 : virtual nsIScriptContext *GetScriptContext(PRUint32 lang);
324 :
325 : // Set a new script language context for this global. The native global
326 : // for the context is created by the context's GetNativeGlobal() method.
327 : virtual nsresult SetScriptContext(PRUint32 lang, nsIScriptContext *aContext);
328 :
329 : virtual void OnFinalize(JSObject* aObject);
330 : virtual void SetScriptsEnabled(bool aEnabled, bool aFireTimeouts);
331 :
332 : virtual bool IsBlackForCC();
333 :
334 : // nsIScriptObjectPrincipal
335 : virtual nsIPrincipal* GetPrincipal();
336 :
337 : // nsIDOMWindow
338 : NS_DECL_NSIDOMWINDOW
339 :
340 : // nsIDOMWindowPerformance
341 : NS_DECL_NSIDOMWINDOWPERFORMANCE
342 :
343 : // nsIDOMJSWindow
344 : NS_DECL_NSIDOMJSWINDOW
345 :
346 : // nsIDOMEventTarget
347 : NS_DECL_NSIDOMEVENTTARGET
348 :
349 : // nsITouchEventReceiver
350 : NS_DECL_NSITOUCHEVENTRECEIVER
351 :
352 : // nsIInlineEventHandlers
353 : NS_DECL_NSIINLINEEVENTHANDLERS
354 :
355 : // nsPIDOMWindow
356 : virtual NS_HIDDEN_(nsPIDOMWindow*) GetPrivateRoot();
357 : virtual NS_HIDDEN_(void) ActivateOrDeactivate(bool aActivate);
358 : virtual NS_HIDDEN_(void) SetActive(bool aActive);
359 : virtual NS_HIDDEN_(void) SetIsBackground(bool aIsBackground);
360 : virtual NS_HIDDEN_(void) SetChromeEventHandler(nsIDOMEventTarget* aChromeEventHandler);
361 :
362 : virtual NS_HIDDEN_(void) SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal);
363 : virtual NS_HIDDEN_(nsIPrincipal*) GetOpenerScriptPrincipal();
364 :
365 : virtual NS_HIDDEN_(PopupControlState) PushPopupControlState(PopupControlState state, bool aForce) const;
366 : virtual NS_HIDDEN_(void) PopPopupControlState(PopupControlState state) const;
367 : virtual NS_HIDDEN_(PopupControlState) GetPopupControlState() const;
368 :
369 : virtual NS_HIDDEN_(nsresult) SaveWindowState(nsISupports **aState);
370 : virtual NS_HIDDEN_(nsresult) RestoreWindowState(nsISupports *aState);
371 : virtual NS_HIDDEN_(void) SuspendTimeouts(PRUint32 aIncrease = 1,
372 : bool aFreezeChildren = true);
373 : virtual NS_HIDDEN_(nsresult) ResumeTimeouts(bool aThawChildren = true);
374 : virtual NS_HIDDEN_(PRUint32) TimeoutSuspendCount();
375 : virtual NS_HIDDEN_(nsresult) FireDelayedDOMEvents();
376 0 : virtual NS_HIDDEN_(bool) IsFrozen() const
377 : {
378 0 : return mIsFrozen;
379 : }
380 :
381 : virtual NS_HIDDEN_(bool) WouldReuseInnerWindow(nsIDocument *aNewDocument);
382 :
383 : virtual NS_HIDDEN_(void) SetDocShell(nsIDocShell* aDocShell);
384 : virtual NS_HIDDEN_(nsresult) SetNewDocument(nsIDocument *aDocument,
385 : nsISupports *aState,
386 : bool aForceReuseInnerWindow);
387 : void DispatchDOMWindowCreated();
388 : virtual NS_HIDDEN_(void) SetOpenerWindow(nsIDOMWindow* aOpener,
389 : bool aOriginalOpener);
390 : virtual NS_HIDDEN_(void) EnsureSizeUpToDate();
391 :
392 : virtual NS_HIDDEN_(nsIDOMWindow*) EnterModalState();
393 : virtual NS_HIDDEN_(void) LeaveModalState(nsIDOMWindow* aWindow);
394 :
395 : virtual NS_HIDDEN_(bool) CanClose();
396 : virtual NS_HIDDEN_(nsresult) ForceClose();
397 :
398 : virtual NS_HIDDEN_(void) SetHasOrientationEventListener();
399 : virtual NS_HIDDEN_(void) RemoveOrientationEventListener();
400 : virtual NS_HIDDEN_(void) MaybeUpdateTouchState();
401 : virtual NS_HIDDEN_(void) UpdateTouchState();
402 : virtual NS_HIDDEN_(bool) DispatchCustomEvent(const char *aEventName);
403 : virtual NS_HIDDEN_(nsresult) SetFullScreenInternal(bool aIsFullScreen, bool aRequireTrust);
404 :
405 : // nsIDOMStorageIndexedDB
406 : NS_DECL_NSIDOMSTORAGEINDEXEDDB
407 :
408 : // nsIInterfaceRequestor
409 : NS_DECL_NSIINTERFACEREQUESTOR
410 :
411 : // Object Management
412 : nsGlobalWindow(nsGlobalWindow *aOuterWindow);
413 :
414 0 : static nsGlobalWindow *FromSupports(nsISupports *supports)
415 : {
416 : // Make sure this matches the casts we do in QueryInterface().
417 0 : return (nsGlobalWindow *)(nsIScriptGlobalObject *)supports;
418 : }
419 : static nsISupports *ToSupports(nsGlobalWindow *win)
420 : {
421 : // Make sure this matches the casts we do in QueryInterface().
422 : return (nsISupports *)(nsIScriptGlobalObject *)win;
423 : }
424 0 : static nsGlobalWindow *FromWrapper(nsIXPConnectWrappedNative *wrapper)
425 : {
426 0 : return FromSupports(wrapper->Native());
427 : }
428 :
429 : /**
430 : * Wrap nsIDOMWindow::GetTop so we can overload the inline GetTop()
431 : * implementation below. (nsIDOMWindow::GetTop simply calls
432 : * nsIDOMWindow::GetRealTop().)
433 : */
434 0 : nsresult GetTop(nsIDOMWindow **aWindow)
435 : {
436 0 : return nsIDOMWindow::GetTop(aWindow);
437 : }
438 :
439 0 : inline nsGlobalWindow *GetTop()
440 : {
441 0 : nsCOMPtr<nsIDOMWindow> top;
442 0 : GetTop(getter_AddRefs(top));
443 0 : if (top)
444 0 : return static_cast<nsGlobalWindow *>(static_cast<nsIDOMWindow *>(top.get()));
445 0 : return nsnull;
446 : }
447 :
448 : // Call this when a modal dialog is about to be opened. Returns
449 : // true if we've reached the state in this top level window where we
450 : // ask the user if further dialogs should be blocked.
451 : bool DialogOpenAttempted();
452 :
453 : // Returns true if dialogs have already been blocked for this
454 : // window.
455 : bool AreDialogsBlocked();
456 :
457 : // Ask the user if further dialogs should be blocked. This is used
458 : // in the cases where we have no modifiable UI to show, in that case
459 : // we show a separate dialog when asking this question.
460 : bool ConfirmDialogAllowed();
461 :
462 : // Prevent further dialogs in this (top level) window
463 : void PreventFurtherDialogs();
464 :
465 : virtual void SetHasAudioAvailableEventListeners();
466 :
467 0 : nsIScriptContext *GetContextInternal()
468 : {
469 0 : if (mOuterWindow) {
470 0 : return GetOuterWindowInternal()->mContext;
471 : }
472 :
473 0 : return mContext;
474 : }
475 :
476 0 : nsIScriptContext *GetScriptContextInternal(PRUint32 aLangID)
477 : {
478 0 : NS_ASSERTION(aLangID == nsIProgrammingLanguage::JAVASCRIPT,
479 : "We don't support this language ID");
480 0 : if (mOuterWindow) {
481 0 : return GetOuterWindowInternal()->mContext;
482 : }
483 :
484 0 : return mContext;
485 : }
486 :
487 0 : nsGlobalWindow *GetOuterWindowInternal()
488 : {
489 0 : return static_cast<nsGlobalWindow *>(GetOuterWindow());
490 : }
491 :
492 0 : nsGlobalWindow *GetCurrentInnerWindowInternal()
493 : {
494 0 : return static_cast<nsGlobalWindow *>(mInnerWindow);
495 : }
496 :
497 : nsGlobalWindow *EnsureInnerWindowInternal()
498 : {
499 : return static_cast<nsGlobalWindow *>(EnsureInnerWindow());
500 : }
501 :
502 0 : bool IsCreatingInnerWindow() const
503 : {
504 0 : return mCreatingInnerWindow;
505 : }
506 :
507 0 : bool IsChromeWindow() const
508 : {
509 0 : return mIsChrome;
510 : }
511 :
512 : nsresult Observe(nsISupports* aSubject, const char* aTopic,
513 : const PRUnichar* aData);
514 :
515 : static void Init();
516 : static void ShutDown();
517 : static void CleanupCachedXBLHandlers(nsGlobalWindow* aWindow);
518 : static bool IsCallerChrome();
519 : static void CloseBlockScriptTerminationFunc(nsISupports *aRef);
520 :
521 : static void RunPendingTimeoutsRecursive(nsGlobalWindow *aTopWindow,
522 : nsGlobalWindow *aWindow);
523 :
524 : friend class WindowStateHolder;
525 :
526 4392 : NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsGlobalWindow,
527 : nsIScriptGlobalObject)
528 :
529 : void InitJavaProperties();
530 :
531 : virtual NS_HIDDEN_(JSObject*)
532 : GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey);
533 :
534 : virtual NS_HIDDEN_(void)
535 : CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
536 : nsScriptObjectHolder<JSObject>& aHandler);
537 :
538 : virtual bool TakeFocus(bool aFocus, PRUint32 aFocusMethod);
539 : virtual void SetReadyForFocus();
540 : virtual void PageHidden();
541 : virtual nsresult DispatchAsyncHashchange(nsIURI *aOldURI, nsIURI *aNewURI);
542 : virtual nsresult DispatchSyncPopState();
543 :
544 : virtual nsresult SetArguments(nsIArray *aArguments, nsIPrincipal *aOrigin);
545 :
546 : static bool DOMWindowDumpEnabled();
547 :
548 : void MaybeForgiveSpamCount();
549 0 : bool IsClosedOrClosing() {
550 : return (mIsClosed ||
551 : mInClose ||
552 : mHavePendingClose ||
553 0 : mCleanedUp);
554 : }
555 :
556 : static void FirePopupBlockedEvent(nsIDOMDocument* aDoc,
557 : nsIDOMWindow *aRequestingWindow, nsIURI *aPopupURI,
558 : const nsAString &aPopupWindowName,
559 : const nsAString &aPopupWindowFeatures);
560 :
561 0 : virtual PRUint32 GetSerial() {
562 0 : return mSerial;
563 : }
564 :
565 0 : static nsGlobalWindow* GetOuterWindowWithId(PRUint64 aWindowID) {
566 0 : if (!sWindowsById) {
567 0 : return nsnull;
568 : }
569 :
570 0 : nsGlobalWindow* outerWindow = sWindowsById->Get(aWindowID);
571 0 : return outerWindow && !outerWindow->IsInnerWindow() ? outerWindow : nsnull;
572 : }
573 :
574 0 : static nsGlobalWindow* GetInnerWindowWithId(PRUint64 aInnerWindowID) {
575 0 : if (!sWindowsById) {
576 0 : return nsnull;
577 : }
578 :
579 0 : nsGlobalWindow* innerWindow = sWindowsById->Get(aInnerWindowID);
580 0 : return innerWindow && innerWindow->IsInnerWindow() ? innerWindow : nsnull;
581 : }
582 :
583 : static bool HasIndexedDBSupport();
584 :
585 : static bool HasPerformanceSupport();
586 :
587 3 : static WindowByIdTable* GetWindowsTable() {
588 3 : return sWindowsById;
589 : }
590 :
591 : void SizeOfIncludingThis(nsWindowSizes* aWindowSizes) const;
592 :
593 : void UnmarkGrayTimers();
594 :
595 : void AddEventTargetObject(nsDOMEventTargetHelper* aObject);
596 : void RemoveEventTargetObject(nsDOMEventTargetHelper* aObject);
597 : private:
598 : // Enable updates for the accelerometer.
599 : void EnableDeviceMotionUpdates();
600 :
601 : // Disables updates for the accelerometer.
602 : void DisableDeviceMotionUpdates();
603 :
604 : // Implements Get{Real,Scriptable}Top.
605 : nsresult GetTopImpl(nsIDOMWindow **aWindow, bool aScriptable);
606 :
607 : protected:
608 : friend class HashchangeCallback;
609 : friend class nsBarProp;
610 :
611 : // Object Management
612 : virtual ~nsGlobalWindow();
613 : void CleanUp(bool aIgnoreModalDialog);
614 : void ClearControllers();
615 : nsresult FinalClose();
616 :
617 : void FreeInnerObjects();
618 : nsGlobalWindow *CallerInnerWindow();
619 :
620 : nsresult InnerSetNewDocument(nsIDocument* aDocument);
621 :
622 : nsresult DefineArgumentsProperty(nsIArray *aArguments);
623 :
624 : // Get the parent, returns null if this is a toplevel window
625 : nsIDOMWindow* GetParentInternal();
626 :
627 : // popup tracking
628 0 : bool IsPopupSpamWindow()
629 : {
630 0 : if (IsInnerWindow() && !mOuterWindow) {
631 0 : return false;
632 : }
633 :
634 0 : return GetOuterWindowInternal()->mIsPopupSpam;
635 : }
636 :
637 0 : void SetPopupSpamWindow(bool aPopup)
638 : {
639 0 : if (IsInnerWindow() && !mOuterWindow) {
640 0 : NS_ERROR("SetPopupSpamWindow() called on inner window w/o an outer!");
641 :
642 0 : return;
643 : }
644 :
645 0 : GetOuterWindowInternal()->mIsPopupSpam = aPopup;
646 : }
647 :
648 : // Window Control Functions
649 : /**
650 : * @param aURL the URL to load in the new window
651 : * @param aName the name to use for the new window
652 : * @param aOptions the window options to use for the new window
653 : * @param aDialog true when called from variants of OpenDialog. If this is
654 : * true, this method will skip popup blocking checks. The
655 : * aDialog argument is passed on to the window watcher.
656 : * @param aCalledNoScript true when called via the [noscript] open()
657 : * and openDialog() methods. When this is true, we do
658 : * NOT want to use the JS stack for things like caller
659 : * determination.
660 : * @param aDoJSFixups true when this is the content-accessible JS version of
661 : * window opening. When true, popups do not cause us to
662 : * throw, we save the caller's principal in the new window
663 : * for later consumption, and we make sure that there is a
664 : * document in the newly-opened window. Note that this
665 : * last will only be done if the newly-opened window is
666 : * non-chrome.
667 : * @param argv The arguments to pass to the new window. The first
668 : * three args, if present, will be aURL, aName, and aOptions. So
669 : * this param only matters if there are more than 3 arguments.
670 : * @param argc The number of arguments in argv.
671 : * @param aExtraArgument Another way to pass arguments in. This is mutually
672 : * exclusive with the argv/argc approach.
673 : * @param aJSCallerContext The calling script's context. This must be nsnull
674 : * when aCalledNoScript is true.
675 : * @param aReturn [out] The window that was opened, if any.
676 : *
677 : * @note that the boolean args are const because the function shouldn't be
678 : * messing with them. That also makes it easier for the compiler to sort out
679 : * its build warning stuff.
680 : */
681 : NS_HIDDEN_(nsresult) OpenInternal(const nsAString& aUrl,
682 : const nsAString& aName,
683 : const nsAString& aOptions,
684 : bool aDialog,
685 : bool aContentModal,
686 : bool aCalledNoScript,
687 : bool aDoJSFixups,
688 : nsIArray *argv,
689 : nsISupports *aExtraArgument,
690 : nsIPrincipal *aCalleePrincipal,
691 : JSContext *aJSCallerContext,
692 : nsIDOMWindow **aReturn);
693 :
694 : static void CloseWindow(nsISupports* aWindow);
695 :
696 : // Timeout Functions
697 : // Language agnostic timeout function (all args passed).
698 : // |interval| is in milliseconds.
699 : nsresult SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
700 : PRInt32 interval,
701 : bool aIsInterval, PRInt32 *aReturn);
702 : nsresult ClearTimeoutOrInterval(PRInt32 aTimerID);
703 :
704 : // JS specific timeout functions (JS args grabbed from context).
705 : nsresult SetTimeoutOrInterval(bool aIsInterval, PRInt32* aReturn);
706 : nsresult ResetTimersForNonBackgroundWindow();
707 :
708 : // The timeout implementation functions.
709 : void RunTimeout(nsTimeout *aTimeout);
710 0 : void RunTimeout() { RunTimeout(nsnull); }
711 :
712 : void ClearAllTimeouts();
713 : // Insert aTimeout into the list, before all timeouts that would
714 : // fire after it, but no earlier than mTimeoutInsertionPoint, if any.
715 : void InsertTimeoutIntoList(nsTimeout *aTimeout);
716 : static void TimerCallback(nsITimer *aTimer, void *aClosure);
717 :
718 : // Helper Functions
719 : nsresult GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner);
720 : nsresult GetTreeOwner(nsIBaseWindow** aTreeOwner);
721 : nsresult GetWebBrowserChrome(nsIWebBrowserChrome** aBrowserChrome);
722 : // GetScrollFrame does not flush. Callers should do it themselves as needed,
723 : // depending on which info they actually want off the scrollable frame.
724 : nsIScrollableFrame *GetScrollFrame();
725 : nsresult SecurityCheckURL(const char *aURL);
726 : nsresult BuildURIfromBase(const char *aURL,
727 : nsIURI **aBuiltURI,
728 : bool *aFreeSecurityPass, JSContext **aCXused);
729 : bool PopupWhitelisted();
730 : PopupControlState RevisePopupAbuseLevel(PopupControlState);
731 : void FireAbuseEvents(bool aBlocked, bool aWindow,
732 : const nsAString &aPopupURL,
733 : const nsAString &aPopupWindowName,
734 : const nsAString &aPopupWindowFeatures);
735 : void FireOfflineStatusEvent();
736 : nsresult FireHashchange(const nsAString &aOldURL, const nsAString &aNewURL);
737 :
738 : void FlushPendingNotifications(mozFlushType aType);
739 : void EnsureReflowFlushAndPaint();
740 : nsresult CheckSecurityWidthAndHeight(PRInt32* width, PRInt32* height);
741 : nsresult CheckSecurityLeftAndTop(PRInt32* left, PRInt32* top);
742 :
743 : // Arguments to this function should have values in app units
744 : nsresult SetCSSViewportWidthAndHeight(nscoord width, nscoord height);
745 : // Arguments to this function should have values in device pixels
746 : nsresult SetDocShellWidthAndHeight(PRInt32 width, PRInt32 height);
747 :
748 : static bool CanSetProperty(const char *aPrefName);
749 :
750 : static void MakeScriptDialogTitle(nsAString &aOutTitle);
751 :
752 : bool CanMoveResizeWindows();
753 :
754 : bool GetBlurSuppression();
755 :
756 : // If aDoFlush is true, we'll flush our own layout; otherwise we'll try to
757 : // just flush our parent and only flush ourselves if we think we need to.
758 : nsresult GetScrollXY(PRInt32* aScrollX, PRInt32* aScrollY,
759 : bool aDoFlush);
760 : nsresult GetScrollMaxXY(PRInt32* aScrollMaxX, PRInt32* aScrollMaxY);
761 :
762 : nsresult GetOuterSize(nsIntSize* aSizeCSSPixels);
763 : nsresult SetOuterSize(PRInt32 aLengthCSSPixels, bool aIsWidth);
764 : nsRect GetInnerScreenRect();
765 :
766 0 : bool IsFrame()
767 : {
768 0 : return GetParentInternal() != nsnull;
769 : }
770 :
771 : // If aLookForCallerOnJSStack is true, this method will look at the JS stack
772 : // to determine who the caller is. If it's false, it'll use |this| as the
773 : // caller.
774 : bool WindowExists(const nsAString& aName, bool aLookForCallerOnJSStack);
775 :
776 : already_AddRefed<nsIWidget> GetMainWidget();
777 : nsIWidget* GetNearestWidget();
778 :
779 0 : void Freeze()
780 : {
781 0 : NS_ASSERTION(!IsFrozen(), "Double-freezing?");
782 0 : mIsFrozen = true;
783 0 : NotifyDOMWindowFrozen(this);
784 0 : }
785 :
786 0 : void Thaw()
787 : {
788 0 : mIsFrozen = false;
789 0 : NotifyDOMWindowThawed(this);
790 0 : }
791 :
792 : bool IsInModalState();
793 :
794 0 : nsTimeout* FirstTimeout() {
795 : // Note: might not actually return an nsTimeout. Use IsTimeout to check.
796 0 : return static_cast<nsTimeout*>(PR_LIST_HEAD(&mTimeouts));
797 : }
798 :
799 0 : nsTimeout* LastTimeout() {
800 : // Note: might not actually return an nsTimeout. Use IsTimeout to check.
801 0 : return static_cast<nsTimeout*>(PR_LIST_TAIL(&mTimeouts));
802 : }
803 :
804 0 : bool IsTimeout(PRCList* aList) {
805 0 : return aList != &mTimeouts;
806 : }
807 :
808 : // Convenience functions for the many methods that need to scale
809 : // from device to CSS pixels or vice versa. Note: if a presentation
810 : // context is not available, they will assume a 1:1 ratio.
811 : PRInt32 DevToCSSIntPixels(PRInt32 px);
812 : PRInt32 CSSToDevIntPixels(PRInt32 px);
813 : nsIntSize DevToCSSIntPixels(nsIntSize px);
814 : nsIntSize CSSToDevIntPixels(nsIntSize px);
815 :
816 : virtual void SetFocusedNode(nsIContent* aNode,
817 : PRUint32 aFocusMethod = 0,
818 : bool aNeedsFocus = false);
819 :
820 : virtual PRUint32 GetFocusMethod();
821 :
822 : virtual bool ShouldShowFocusRing();
823 :
824 : virtual void SetKeyboardIndicators(UIStateChangeType aShowAccelerators,
825 : UIStateChangeType aShowFocusRings);
826 : virtual void GetKeyboardIndicators(bool* aShowAccelerators,
827 : bool* aShowFocusRings);
828 :
829 : void UpdateCanvasFocus(bool aFocusChanged, nsIContent* aNewContent);
830 :
831 : already_AddRefed<nsPIWindowRoot> GetTopWindowRoot();
832 :
833 : static void NotifyDOMWindowDestroyed(nsGlobalWindow* aWindow);
834 : void NotifyWindowIDDestroyed(const char* aTopic);
835 :
836 : static void NotifyDOMWindowFrozen(nsGlobalWindow* aWindow);
837 : static void NotifyDOMWindowThawed(nsGlobalWindow* aWindow);
838 :
839 : void ClearStatus();
840 :
841 : virtual void UpdateParentTarget();
842 :
843 : bool GetIsTabModalPromptAllowed();
844 :
845 : inline PRInt32 DOMMinTimeoutValue() const;
846 :
847 : // When adding new member variables, be careful not to create cycles
848 : // through JavaScript. If there is any chance that a member variable
849 : // could own objects that are implemented in JavaScript, then those
850 : // objects will keep the global object (this object) alive. To prevent
851 : // these cycles, ownership of such members must be released in
852 : // |CleanUp| and |SetDocShell|.
853 :
854 : // This member is also used on both inner and outer windows, but
855 : // for slightly different purposes. On inner windows it means the
856 : // inner window is held onto by session history and should not
857 : // change. On outer windows it means that the window is in a state
858 : // where we don't want to force creation of a new inner window since
859 : // we're in the middle of doing just that.
860 : bool mIsFrozen : 1;
861 :
862 : // True if the Java properties have been initialized on this
863 : // window. Only used on inner windows.
864 : bool mDidInitJavaProperties : 1;
865 :
866 : // These members are only used on outer window objects. Make sure
867 : // you never set any of these on an inner object!
868 : bool mFullScreen : 1;
869 : bool mIsClosed : 1;
870 : bool mInClose : 1;
871 : // mHavePendingClose means we've got a termination function set to
872 : // close us when the JS stops executing or that we have a close
873 : // event posted. If this is set, just ignore window.close() calls.
874 : bool mHavePendingClose : 1;
875 : bool mHadOriginalOpener : 1;
876 : bool mIsPopupSpam : 1;
877 :
878 : // Indicates whether scripts are allowed to close this window.
879 : bool mBlockScriptedClosingFlag : 1;
880 :
881 : // Track what sorts of events we need to fire when thawed
882 : bool mFireOfflineStatusChangeEventOnThaw : 1;
883 :
884 : // Indicates whether we're in the middle of creating an initializing
885 : // a new inner window object.
886 : bool mCreatingInnerWindow : 1;
887 :
888 : // Fast way to tell if this is a chrome window (without having to QI).
889 : bool mIsChrome : 1;
890 :
891 : // Hack to indicate whether a chrome window needs its message manager
892 : // to be disconnected, since clean up code is shared in the global
893 : // window superclass.
894 : bool mCleanMessageManager : 1;
895 :
896 : // Indicates that the current document has never received a document focus
897 : // event.
898 : bool mNeedsFocus : 1;
899 : bool mHasFocus : 1;
900 :
901 : // whether to show keyboard accelerators
902 : bool mShowAccelerators : 1;
903 :
904 : // whether to show focus rings
905 : bool mShowFocusRings : 1;
906 :
907 : // when true, show focus rings for the current focused content only.
908 : // This will be reset when another element is focused
909 : bool mShowFocusRingForContent : 1;
910 :
911 : // true if tab navigation has occurred for this window. Focus rings
912 : // should be displayed.
913 : bool mFocusByKeyOccurred : 1;
914 :
915 : // Indicates whether this window is getting device motion change events
916 : bool mHasDeviceMotion : 1;
917 :
918 : // whether we've sent the destroy notification for our window id
919 : bool mNotifiedIDDestroyed : 1;
920 :
921 : nsCOMPtr<nsIScriptContext> mContext;
922 : nsWeakPtr mOpener;
923 : nsCOMPtr<nsIControllers> mControllers;
924 : nsCOMPtr<nsIArray> mArguments;
925 : nsCOMPtr<nsIArray> mArgumentsLast;
926 : nsCOMPtr<nsIPrincipal> mArgumentsOrigin;
927 : nsRefPtr<Navigator> mNavigator;
928 : nsRefPtr<nsScreen> mScreen;
929 : nsRefPtr<nsPerformance> mPerformance;
930 : nsRefPtr<nsDOMWindowList> mFrames;
931 : nsRefPtr<nsBarProp> mMenubar;
932 : nsRefPtr<nsBarProp> mToolbar;
933 : nsRefPtr<nsBarProp> mLocationbar;
934 : nsRefPtr<nsBarProp> mPersonalbar;
935 : nsRefPtr<nsBarProp> mStatusbar;
936 : nsRefPtr<nsBarProp> mScrollbars;
937 : nsCOMPtr<nsIWeakReference> mWindowUtils;
938 : nsString mStatus;
939 : nsString mDefaultStatus;
940 : // index 0->language_id 1, so index MAX-1 == language_id MAX
941 : nsGlobalWindowObserver* mObserver;
942 : #ifndef MOZ_DISABLE_DOMCRYPTO
943 : nsCOMPtr<nsIDOMCrypto> mCrypto;
944 : #endif
945 : nsCOMPtr<nsIDOMStorage> mLocalStorage;
946 : nsCOMPtr<nsIDOMStorage> mSessionStorage;
947 :
948 : nsCOMPtr<nsIXPConnectJSObjectHolder> mInnerWindowHolder;
949 : nsCOMPtr<nsIPrincipal> mOpenerScriptPrincipal; // strong; used to determine
950 : // whether to clear scope
951 :
952 : // These member variable are used only on inner windows.
953 : nsRefPtr<nsEventListenerManager> mListenerManager;
954 : // mTimeouts is generally sorted by mWhen, unless mTimeoutInsertionPoint is
955 : // non-null. In that case, the dummy timeout pointed to by
956 : // mTimeoutInsertionPoint may have a later mWhen than some of the timeouts
957 : // that come after it.
958 : PRCList mTimeouts;
959 : // If mTimeoutInsertionPoint is non-null, insertions should happen after it.
960 : // This is a dummy timeout at the moment; if that ever changes, the logic in
961 : // ResetTimersForNonBackgroundWindow needs to change.
962 : nsTimeout* mTimeoutInsertionPoint;
963 : PRUint32 mTimeoutPublicIdCounter;
964 : PRUint32 mTimeoutFiringDepth;
965 : nsRefPtr<nsLocation> mLocation;
966 : nsRefPtr<nsHistory> mHistory;
967 :
968 : // Holder of the dummy java plugin, used to expose window.java and
969 : // window.packages.
970 : nsRefPtr<nsDummyJavaPluginOwner> mDummyJavaPluginOwner;
971 :
972 : // These member variables are used on both inner and the outer windows.
973 : nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
974 : nsCOMPtr<nsIDocument> mDoc; // For fast access to principals
975 : JSObject* mJSObject;
976 :
977 : typedef nsCOMArray<nsIDOMStorageEvent> nsDOMStorageEventArray;
978 : nsDOMStorageEventArray mPendingStorageEvents;
979 : nsAutoPtr< nsDataHashtable<nsStringHashKey, bool> > mPendingStorageEventsObsolete;
980 :
981 : PRUint32 mTimeoutsSuspendDepth;
982 :
983 : // the method that was used to focus mFocusedNode
984 : PRUint32 mFocusMethod;
985 :
986 : PRUint32 mSerial;
987 :
988 : #ifdef DEBUG
989 : bool mSetOpenerWindowCalled;
990 : nsCOMPtr<nsIURI> mLastOpenedURI;
991 : #endif
992 :
993 : bool mCleanedUp, mCallCleanUpAfterModalDialogCloses;
994 :
995 : nsCOMPtr<nsIDOMOfflineResourceList> mApplicationCache;
996 :
997 : nsDataHashtable<nsVoidPtrHashKey, JSObject*> mCachedXBLPrototypeHandlers;
998 :
999 : nsCOMPtr<nsIDocument> mSuspendedDoc;
1000 :
1001 : nsCOMPtr<nsIIDBFactory> mIndexedDB;
1002 :
1003 : // In the case of a "trusted" dialog (@see PopupControlState), we
1004 : // set this counter to ensure a max of MAX_DIALOG_LIMIT
1005 : PRUint32 mDialogAbuseCount;
1006 :
1007 : // This holds the time when the last modal dialog was shown, if two
1008 : // dialogs are shown within CONCURRENT_DIALOG_TIME_LIMIT the
1009 : // checkbox is shown. In the case of ShowModalDialog another Confirm
1010 : // dialog will be shown, the result of the checkbox/confirm dialog
1011 : // will be stored in mDialogDisabled variable.
1012 : TimeStamp mLastDialogQuitTime;
1013 : bool mDialogDisabled;
1014 :
1015 : nsRefPtr<nsDOMMozURLProperty> mURLProperty;
1016 :
1017 : nsTHashtable<nsPtrHashKey<nsDOMEventTargetHelper> > mEventTargetObjects;
1018 :
1019 : friend class nsDOMScriptableHelper;
1020 : friend class nsDOMWindowUtils;
1021 : friend class PostMessageEvent;
1022 :
1023 : static WindowByIdTable* sWindowsById;
1024 : static bool sWarnedAboutWindowInternal;
1025 : };
1026 :
1027 : /*
1028 : * nsGlobalChromeWindow inherits from nsGlobalWindow. It is the global
1029 : * object created for a Chrome Window only.
1030 : */
1031 : class nsGlobalChromeWindow : public nsGlobalWindow,
1032 : public nsIDOMChromeWindow
1033 : {
1034 : public:
1035 : // nsISupports
1036 : NS_DECL_ISUPPORTS_INHERITED
1037 :
1038 : // nsIDOMChromeWindow interface
1039 : NS_DECL_NSIDOMCHROMEWINDOW
1040 :
1041 0 : nsGlobalChromeWindow(nsGlobalWindow *aOuterWindow)
1042 0 : : nsGlobalWindow(aOuterWindow)
1043 : {
1044 0 : mIsChrome = true;
1045 0 : mCleanMessageManager = true;
1046 0 : }
1047 :
1048 0 : ~nsGlobalChromeWindow()
1049 0 : {
1050 0 : NS_ABORT_IF_FALSE(mCleanMessageManager,
1051 : "chrome windows may always disconnect the msg manager");
1052 0 : if (mMessageManager) {
1053 : static_cast<nsFrameMessageManager *>(
1054 0 : mMessageManager.get())->Disconnect();
1055 : }
1056 :
1057 0 : mCleanMessageManager = false;
1058 0 : }
1059 :
1060 1464 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsGlobalChromeWindow,
1061 : nsGlobalWindow)
1062 :
1063 : nsCOMPtr<nsIBrowserDOMWindow> mBrowserDOMWindow;
1064 : nsCOMPtr<nsIChromeFrameMessageManager> mMessageManager;
1065 : };
1066 :
1067 : /*
1068 : * nsGlobalModalWindow inherits from nsGlobalWindow. It is the global
1069 : * object created for a modal content windows only (i.e. not modal
1070 : * chrome dialogs).
1071 : */
1072 : class nsGlobalModalWindow : public nsGlobalWindow,
1073 : public nsIDOMModalContentWindow
1074 0 : {
1075 : public:
1076 0 : nsGlobalModalWindow(nsGlobalWindow *aOuterWindow)
1077 0 : : nsGlobalWindow(aOuterWindow)
1078 : {
1079 0 : mIsModalContentWindow = true;
1080 0 : }
1081 :
1082 : NS_DECL_ISUPPORTS_INHERITED
1083 : NS_DECL_NSIDOMMODALCONTENTWINDOW
1084 :
1085 1464 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsGlobalModalWindow, nsGlobalWindow)
1086 :
1087 : virtual NS_HIDDEN_(nsresult) SetNewDocument(nsIDocument *aDocument,
1088 : nsISupports *aState,
1089 : bool aForceReuseInnerWindow);
1090 :
1091 : protected:
1092 : nsCOMPtr<nsIVariant> mReturnValue;
1093 : };
1094 :
1095 : /* factory function */
1096 : nsresult
1097 : NS_NewScriptGlobalObject(bool aIsChrome, bool aIsModalContentWindow,
1098 : nsIScriptGlobalObject **aResult);
1099 :
1100 : #endif /* nsGlobalWindow_h___ */
|