Back to index

lightning-sunbird  0.9+nobinonly
nsPIDOMWindow.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* vim: set ts=2 sw=2 et tw=80: */
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 
00040 #ifndef nsPIDOMWindow_h__
00041 #define nsPIDOMWindow_h__
00042 
00043 #include "nsISupports.h"
00044 #include "nsIDOMLocation.h"
00045 #include "nsIDOMXULCommandDispatcher.h"
00046 #include "nsIDOMElement.h"
00047 #include "nsIDOMWindowInternal.h"
00048 #include "nsIChromeEventHandler.h"
00049 #include "nsIDOMDocument.h"
00050 #include "nsIURI.h"
00051 #include "nsCOMPtr.h"
00052 
00053 class nsIPrincipal;
00054 
00055 // Popup control state enum. The values in this enum must go from most
00056 // permissive to least permissive so that it's safe to push state in
00057 // all situations. Pushing popup state onto the stack never makes the
00058 // current popup state less permissive (see
00059 // nsGlobalWindow::PushPopupControlState()).
00060 enum PopupControlState {
00061   openAllowed = 0,  // open that window without worries
00062   openControlled,   // it's a popup, but allow it
00063   openAbused,       // it's a popup. disallow it, but allow domain override.
00064   openOverridden    // disallow window open
00065 };
00066 
00067 // permissible values for GetOpenAllow
00068 enum OpenAllowValue {
00069   allowNot = 0,     // the window opening is denied
00070   allowNoAbuse,     // allowed: not a popup
00071   allowWhitelisted  // allowed: it's whitelisted or popup blocking is disabled
00072 };
00073 
00074 class nsIDocShell;
00075 class nsIFocusController;
00076 class nsIDocument;
00077 struct nsTimeout;
00078 
00079 #define NS_PIDOMWINDOW_IID \
00080 { 0x55f987bc, 0xca30, 0x494c, \
00081   { 0xa9, 0x85, 0xf1, 0xf3, 0x4b, 0x9d, 0x47, 0xd8 } }
00082 
00083 class nsPIDOMWindow : public nsIDOMWindowInternal
00084 {
00085 public:
00086   NS_DEFINE_STATIC_IID_ACCESSOR(NS_PIDOMWINDOW_IID)
00087 
00088   virtual nsPIDOMWindow* GetPrivateRoot() = 0;
00089 
00090   virtual nsresult GetObjectProperty(const PRUnichar* aProperty,
00091                                      nsISupports** aObject) = 0;
00092 
00093   // This is private because activate/deactivate events are not part
00094   // of the DOM spec.
00095   virtual nsresult Activate() = 0;
00096   virtual nsresult Deactivate() = 0;
00097 
00098   nsIChromeEventHandler* GetChromeEventHandler() const
00099   {
00100     return mChromeEventHandler;
00101   }
00102 
00103   PRBool HasMutationListeners(PRUint32 aMutationEventType) const
00104   {
00105     const nsPIDOMWindow *win;
00106 
00107     if (IsOuterWindow()) {
00108       win = GetCurrentInnerWindow();
00109 
00110       if (!win) {
00111         NS_ERROR("No current inner window available!");
00112 
00113         return PR_FALSE;
00114       }
00115     } else {
00116       if (!mOuterWindow) {
00117         NS_ERROR("HasMutationListeners() called on orphan inner window!");
00118 
00119         return PR_FALSE;
00120       }
00121 
00122       win = this;
00123     }
00124 
00125     return (win->mMutationBits & aMutationEventType) != 0;
00126   }
00127 
00128   void SetMutationListeners(PRUint32 aType)
00129   {
00130     nsPIDOMWindow *win;
00131 
00132     if (IsOuterWindow()) {
00133       win = GetCurrentInnerWindow();
00134 
00135       if (!win) {
00136         NS_ERROR("No inner window available to set mutation bits on!");
00137 
00138         return;
00139       }
00140     } else {
00141       if (!mOuterWindow) {
00142         NS_ERROR("HasMutationListeners() called on orphan inner window!");
00143 
00144         return;
00145       }
00146 
00147       win = this;
00148     }
00149 
00150     win->mMutationBits |= aType;
00151   }
00152 
00153   virtual nsIFocusController* GetRootFocusController() = 0;
00154 
00155   // GetExtantDocument provides a backdoor to the DOM GetDocument accessor
00156   nsIDOMDocument* GetExtantDocument() const
00157   {
00158     return mDocument;
00159   }
00160 
00161   // Internal getter/setter for the frame element, this version of the
00162   // getter crosses chrome boundaries whereas the public scriptable
00163   // one doesn't for security reasons.
00164   nsIDOMElement* GetFrameElementInternal() const
00165   {
00166     if (mOuterWindow) {
00167       return mOuterWindow->GetFrameElementInternal();
00168     }
00169 
00170     NS_ASSERTION(!IsInnerWindow(),
00171                  "GetFrameElementInternal() called on orphan inner window");
00172 
00173     return mFrameElement;
00174   }
00175 
00176   void SetFrameElementInternal(nsIDOMElement *aFrameElement)
00177   {
00178     if (IsOuterWindow()) {
00179       mFrameElement = aFrameElement;
00180 
00181       return;
00182     }
00183 
00184     if (!mOuterWindow) {
00185       NS_ERROR("frameElement set on inner window with no outer!");
00186 
00187       return;
00188     }
00189 
00190     mOuterWindow->SetFrameElementInternal(aFrameElement);
00191   }
00192 
00193   PRBool IsLoadingOrRunningTimeout() const
00194   {
00195     const nsPIDOMWindow *win = GetCurrentInnerWindow();
00196 
00197     if (!win) {
00198       win = this;
00199     }
00200 
00201     return !win->mIsDocumentLoaded || win->mRunningTimeout;
00202   }
00203 
00204   // Check whether a document is currently loading
00205   PRBool IsLoading() const
00206   {
00207     const nsPIDOMWindow *win;
00208 
00209     if (IsOuterWindow()) {
00210       win = GetCurrentInnerWindow();
00211 
00212       if (!win) {
00213         NS_ERROR("No current inner window available!");
00214 
00215         return PR_FALSE;
00216       }
00217     } else {
00218       if (!mOuterWindow) {
00219         NS_ERROR("IsLoading() called on orphan inner window!");
00220 
00221         return PR_FALSE;
00222       }
00223 
00224       win = this;
00225     }
00226 
00227     return !win->mIsDocumentLoaded;
00228   }
00229 
00230   PRBool IsHandlingResizeEvent() const
00231   {
00232     const nsPIDOMWindow *win;
00233 
00234     if (IsOuterWindow()) {
00235       win = GetCurrentInnerWindow();
00236 
00237       if (!win) {
00238         NS_ERROR("No current inner window available!");
00239 
00240         return PR_FALSE;
00241       }
00242     } else {
00243       if (!mOuterWindow) {
00244         NS_ERROR("IsHandlingResizeEvent() called on orphan inner window!");
00245 
00246         return PR_FALSE;
00247       }
00248 
00249       win = this;
00250     }
00251 
00252     return win->mIsHandlingResizeEvent;
00253   }
00254 
00255   // DO NOT USE THIS FUNCTION.  IT DOES NOTHING.  USE
00256   // SetOpenerScriptPrincipal INSTEAD.
00257   virtual void SetOpenerScriptURL(nsIURI* aURI) = 0;
00258 
00259   virtual PopupControlState PushPopupControlState(PopupControlState aState,
00260                                                   PRBool aForce) const = 0;
00261   virtual void PopPopupControlState(PopupControlState state) const = 0;
00262   virtual PopupControlState GetPopupControlState() const = 0;
00263 
00264   // GetOpenAllow must not be called on a window that no longer has a docshell
00265   // This function is deprecated.  It will assume that there is no existing
00266   // window with name aName for purposes of its answer.  Expect this function
00267   // to get removed soon!
00268   virtual OpenAllowValue GetOpenAllow(const nsAString &aName) = 0;
00269 
00270   // Returns an object containing the window's state.  This also suspends
00271   // all running timeouts in the window.
00272   virtual nsresult SaveWindowState(nsISupports **aState) = 0;
00273 
00274   // Restore the window state from aState.
00275   virtual nsresult RestoreWindowState(nsISupports *aState) = 0;
00276 
00277   // Resume suspended timeouts in this window and in child windows.
00278   virtual nsresult ResumeTimeouts() = 0;
00279 
00280   nsPIDOMWindow *GetOuterWindow()
00281   {
00282     return mIsInnerWindow ? mOuterWindow : this;
00283   }
00284 
00285   nsPIDOMWindow *GetCurrentInnerWindow() const
00286   {
00287     return mInnerWindow;
00288   }
00289 
00290   PRBool IsInnerWindow() const
00291   {
00292     return mIsInnerWindow;
00293   }
00294 
00295   PRBool IsOuterWindow() const
00296   {
00297     return !IsInnerWindow();
00298   }
00299 
00300   virtual PRBool WouldReuseInnerWindow(nsIDocument *aNewDocument) = 0;
00301 
00302 protected:
00303   // The nsPIDOMWindow constructor. The aOuterWindow argument should
00304   // be null if and only if the created window itself is an outer
00305   // window. In all other cases aOuterWindow should be the outer
00306   // window for the inner window that is being created.
00307   nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
00308     : mFrameElement(nsnull), mRunningTimeout(nsnull), mMutationBits(0),
00309       mIsDocumentLoaded(PR_FALSE), mIsHandlingResizeEvent(PR_FALSE),
00310       mIsInnerWindow(aOuterWindow != nsnull), mInnerWindow(nsnull),
00311       mOuterWindow(aOuterWindow)
00312   {
00313   }
00314 
00315   // These two variables are special in that they're set to the same
00316   // value on both the outer window and the current inner window. Make
00317   // sure you keep them in sync!
00318   nsCOMPtr<nsIChromeEventHandler> mChromeEventHandler; // strong
00319   nsCOMPtr<nsIDOMDocument> mDocument; // strong
00320 
00321   // These members are only used on outer windows.
00322   nsIDOMElement *mFrameElement; // weak
00323 
00324   // These variables are only used on inner windows.
00325   nsTimeout             *mRunningTimeout;
00326 
00327   PRUint32               mMutationBits;
00328 
00329   PRPackedBool           mIsDocumentLoaded;
00330   PRPackedBool           mIsHandlingResizeEvent;
00331   PRPackedBool           mIsInnerWindow;
00332 
00333   // And these are the references between inner and outer windows.
00334   nsPIDOMWindow         *mInnerWindow;
00335   nsPIDOMWindow         *mOuterWindow;
00336 };
00337 
00338 #define NS_PIDOMWINDOW_MOZILLA_1_8_BRANCH_IID \
00339 { 0xa9b7f235, 0x4c98, 0x4257, \
00340   { 0xb1, 0x1a, 0xbe, 0x53, 0x39, 0x69, 0xdf, 0x2a } }
00341 
00342 class nsPIDOMWindow_MOZILLA_1_8_BRANCH : public nsPIDOMWindow
00343 {
00344 public:
00345   NS_DEFINE_STATIC_IID_ACCESSOR(NS_PIDOMWINDOW_MOZILLA_1_8_BRANCH_IID)
00346 
00347   
00354   virtual void SetOpenerWindow(nsIDOMWindowInternal *aOpener,
00355                                PRBool aOriginalOpener) = 0;
00356 
00361   virtual nsresult FireDelayedDOMEvents() = 0;
00362 
00367   virtual void EnterModalState() = 0;
00368   virtual void LeaveModalState() = 0;
00369 
00370 protected:
00371   nsPIDOMWindow_MOZILLA_1_8_BRANCH(nsPIDOMWindow *aOuterWindow)
00372     : nsPIDOMWindow(aOuterWindow)
00373   {
00374   }                                     
00375 };
00376   
00377 #define NS_PIDOMWINDOW_MOZILLA_1_8_BRANCH2_IID \
00378 { 0xddd4affd, 0x6ad4, 0x44b4, \
00379  { 0xa8, 0xfc, 0x78, 0x1d, 0xbd, 0xf1, 0x87, 0x1d } }
00380 
00381 class nsPIDOMWindow_MOZILLA_1_8_BRANCH2 : public nsPIDOMWindow_MOZILLA_1_8_BRANCH
00382 {
00383 public:
00384   NS_DEFINE_STATIC_IID_ACCESSOR(NS_PIDOMWINDOW_MOZILLA_1_8_BRANCH2_IID)
00385 
00386   // Tell this window who opened it.  This only has an effect if there is
00387   // either no document currently in the window or if the document is the
00388   // original document this window came with (an about:blank document either
00389   // preloaded into it when it was created, or created by
00390   // CreateAboutBlankContentViewer()).
00391   virtual void SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal) = 0;
00392   // Ask this window who opened it.
00393   virtual nsIPrincipal* GetOpenerScriptPrincipal() = 0;
00394 
00395 protected:
00396   nsPIDOMWindow_MOZILLA_1_8_BRANCH2(nsPIDOMWindow *aOuterWindow)
00397     : nsPIDOMWindow_MOZILLA_1_8_BRANCH(aOuterWindow)
00398   {
00399   }                                     
00400 };
00401   
00402 #ifdef _IMPL_NS_LAYOUT
00403 PopupControlState
00404 PushPopupControlState(PopupControlState aState, PRBool aForce);
00405 
00406 void
00407 PopPopupControlState(PopupControlState aState);
00408 
00409 #define NS_AUTO_POPUP_STATE_PUSHER nsAutoPopupStatePusherInternal
00410 #else
00411 #define NS_AUTO_POPUP_STATE_PUSHER nsAutoPopupStatePusherExternal
00412 #endif
00413 
00414 // Helper class that helps with pushing and popping popup control
00415 // state. Note that this class looks different from within code that's
00416 // part of the layout library than it does in code outside the layout
00417 // library.  We give the two object layouts different names so the symbols
00418 // don't conflict, but code should always use the name
00419 // |nsAutoPopupStatePusher|.
00420 class NS_AUTO_POPUP_STATE_PUSHER
00421 {
00422 public:
00423 #ifdef _IMPL_NS_LAYOUT
00424   NS_AUTO_POPUP_STATE_PUSHER(PopupControlState aState, PRBool aForce = PR_FALSE)
00425     : mOldState(::PushPopupControlState(aState, aForce))
00426   {
00427   }
00428 
00429   ~NS_AUTO_POPUP_STATE_PUSHER()
00430   {
00431     PopPopupControlState(mOldState);
00432   }
00433 #else
00434   NS_AUTO_POPUP_STATE_PUSHER(nsPIDOMWindow *aWindow, PopupControlState aState)
00435     : mWindow(aWindow), mOldState(openAbused)
00436   {
00437     if (aWindow) {
00438       mOldState = aWindow->PushPopupControlState(aState, PR_FALSE);
00439     }
00440   }
00441 
00442   ~NS_AUTO_POPUP_STATE_PUSHER()
00443   {
00444     if (mWindow) {
00445       mWindow->PopPopupControlState(mOldState);
00446     }
00447   }
00448 #endif
00449 
00450 protected:
00451 #ifndef _IMPL_NS_LAYOUT
00452   nsCOMPtr<nsPIDOMWindow> mWindow;
00453 #endif
00454   PopupControlState mOldState;
00455 
00456 private:
00457   // Hide so that this class can only be stack-allocated
00458   static void* operator new(size_t /*size*/) CPP_THROW_NEW { return nsnull; }
00459   static void operator delete(void* /*memory*/) {}
00460 };
00461 
00462 #define nsAutoPopupStatePusher NS_AUTO_POPUP_STATE_PUSHER
00463 
00464 #endif // nsPIDOMWindow_h__