Back to index

lightning-sunbird  0.9+nobinonly
nsContentUtils.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
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 Communicator client code, released
00017  * March 31, 1998.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Netscape Communications Corporation.
00021  * Portions created by the Initial Developer are Copyright (C) 1998
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 /* A namespace class for static content utilities. */
00041 
00042 #ifndef nsContentUtils_h___
00043 #define nsContentUtils_h___
00044 
00045 #include "jspubtd.h"
00046 #include "nsAString.h"
00047 #include "nsIDOMScriptObjectFactory.h"
00048 #include "nsIJSContextStack.h"
00049 #include "nsIScriptContext.h"
00050 #include "nsCOMArray.h"
00051 #include "nsIStatefulFrame.h"
00052 #include "nsIPref.h"
00053 #include "nsINodeInfo.h"
00054 #include "nsNodeInfoManager.h"
00055 #include "nsContentList.h"
00056 #include "nsVoidArray.h"
00057 
00058 class nsIXPConnect;
00059 class nsIContent;
00060 class nsIDOMNode;
00061 class nsIDocument;
00062 class nsIDocShell;
00063 class nsINameSpaceManager;
00064 class nsIScriptSecurityManager;
00065 class nsIThreadJSContextStack;
00066 class nsIParserService;
00067 class nsIIOService;
00068 class nsIURI;
00069 class imgIDecoderObserver;
00070 class imgIRequest;
00071 class imgILoader;
00072 class nsIPrefBranch;
00073 class nsIImage;
00074 class nsIImageLoadingContent;
00075 class nsIDOMHTMLFormElement;
00076 class nsIDOMDocument;
00077 class nsIConsoleService;
00078 class nsIStringBundleService;
00079 class nsIStringBundle;
00080 class nsIJSRuntimeService;
00081 class nsIScriptGlobalObject;
00082 struct JSRuntime;
00083 class nsPIDOMWindow;
00084 #ifdef MOZ_XTF
00085 class nsIXTFService;
00086 #endif
00087 
00088 class nsContentUtils
00089 {
00090 public:
00091   static nsresult Init();
00092 
00093   // You MUST pass the old ownerDocument of aContent in as aOldDocument and the
00094   // new one as aNewDocument.  aNewParent is allowed to be null; in that case
00095   // aNewDocument will be assumed to be the parent.  Note that at this point
00096   // the actual ownerDocument of aContent may not yet be aNewDocument.
00097   // XXXbz but then if it gets wrapped after we do this call but before its
00098   // ownerDocument actually changes, things will break...
00099   static nsresult ReparentContentWrapper(nsIContent *aContent,
00100                                          nsIContent *aNewParent,
00101                                          nsIDocument *aNewDocument,
00102                                          nsIDocument *aOldDocument);
00103 
00108   static nsresult ReparentContentWrappersInScope(nsIScriptGlobalObject *aOldScope,
00109                                                  nsIScriptGlobalObject *aNewScope);
00110 
00111   static PRBool   IsCallerChrome();
00112 
00113   static PRBool   IsCallerTrustedForRead();
00114 
00115   static PRBool   IsCallerTrustedForWrite();
00116 
00121   static PRBool   IsCallerTrustedForCapability(const char* aCapability);
00122 
00123   /*
00124    * Returns true if the nodes are both in the same document or
00125    * if neither is in a document.
00126    * Returns false if the nodes are not in the same document.
00127    */
00128   static PRBool   InSameDoc(nsIDOMNode *aNode,
00129                             nsIDOMNode *aOther);
00130 
00144   static PRBool ContentIsDescendantOf(nsIContent* aPossibleDescendant,
00145                                       nsIContent* aPossibleAncestor);
00146 
00147   /*
00148    * This method fills the |aArray| with all ancestor nodes of |aNode|
00149    * including |aNode| at the zero index.
00150    *
00151    * These elements were |nsIDOMNode*|s before casting to |void*| and must
00152    * be cast back to |nsIDOMNode*| on usage, or bad things will happen.
00153    */
00154   static nsresult GetAncestors(nsIDOMNode* aNode,
00155                                nsVoidArray* aArray);
00156 
00157   /*
00158    * This method fills |aAncestorNodes| with all ancestor nodes of |aNode|
00159    * including |aNode| (QI'd to nsIContent) at the zero index.
00160    * For each ancestor, there is a corresponding element in |aAncestorOffsets|
00161    * which is the IndexOf the child in relation to its parent.
00162    *
00163    * The elements of |aAncestorNodes| were |nsIContent*|s before casting to
00164    * |void*| and must be cast back to |nsIContent*| on usage, or bad things
00165    * will happen.
00166    *
00167    * This method just sucks.
00168    */
00169   static nsresult GetAncestorsAndOffsets(nsIDOMNode* aNode,
00170                                          PRInt32 aOffset,
00171                                          nsVoidArray* aAncestorNodes,
00172                                          nsVoidArray* aAncestorOffsets);
00173 
00174   /*
00175    * The out parameter, |aCommonAncestor| will be the closest node, if any,
00176    * to both |aNode| and |aOther| which is also an ancestor of each.
00177    */
00178   static nsresult GetCommonAncestor(nsIDOMNode *aNode,
00179                                     nsIDOMNode *aOther,
00180                                     nsIDOMNode** aCommonAncestor);
00181 
00182   /*
00183    * |aDifferentNodes| will contain up to 3 elements.
00184    * The first, if present, is the common ancestor of |aNode| and |aOther|.
00185    * The second, if present, is the ancestor node of |aNode| which is
00186    * closest to the common ancestor, but not an ancestor of |aOther|.
00187    * The third, if present, is the ancestor node of |aOther| which is
00188    * closest to the common ancestor, but not an ancestor of |aNode|.
00189    *
00190    * @throws NS_ERROR_FAILURE if aNode and aOther are disconnected.
00191    */
00192   static nsresult GetFirstDifferentAncestors(nsIDOMNode *aNode,
00193                                              nsIDOMNode *aOther,
00194                                              nsCOMArray<nsIDOMNode>& aDifferentNodes);
00195 
00210   static PRUint16 ComparePositionWithAncestors(nsIDOMNode *aNode,
00211                                                nsIDOMNode *aOther);
00212 
00223   static PRUint16 ReverseDocumentPosition(PRUint16 aDocumentPosition);
00224 
00225   static PRUint32 CopyNewlineNormalizedUnicodeTo(const nsAString& aSource,
00226                                                  PRUint32 aSrcOffset,
00227                                                  PRUnichar* aDest,
00228                                                  PRUint32 aLength,
00229                                                  PRBool& aLastCharCR);
00230 
00231   static PRUint32 CopyNewlineNormalizedUnicodeTo(nsReadingIterator<PRUnichar>& aSrcStart, const nsReadingIterator<PRUnichar>& aSrcEnd, nsAString& aDest);
00232 
00233   static nsISupports *
00234   GetClassInfoInstance(nsDOMClassInfoID aID);
00235 
00236   static const nsDependentSubstring TrimCharsInSet(const char* aSet,
00237                                                    const nsAString& aValue);
00238 
00239   static const nsDependentSubstring TrimWhitespace(const nsAString& aStr,
00240                                                    PRBool aTrimTrailing = PR_TRUE);
00241 
00242   static void Shutdown();
00243 
00251   static nsresult CheckSameOrigin(nsIDOMNode* aTrustedNode,
00252                                   nsIDOMNode* aUnTrustedNode);
00253 
00254   // Check if the (JS) caller can access aNode.
00255   static PRBool CanCallerAccess(nsIDOMNode *aNode);
00256 
00257   // Check if the (JS) caller can access aWindow.
00258   // aWindow can be either outer or inner window.
00259   static PRBool CanCallerAccess(nsPIDOMWindow* aWindow);
00260 
00267   static nsIDocShell *GetDocShellFromCaller();
00268 
00291   static nsIDOMDocument *GetDocumentFromCaller();
00292 
00300   static nsIDOMDocument *GetDocumentFromContext();
00301 
00302   // Check if a node is in the document prolog, i.e. before the document
00303   // element.
00304   static PRBool InProlog(nsIDOMNode *aNode);
00305 
00306   static nsIParserService* GetParserServiceWeakRef();
00307 
00308   static nsINameSpaceManager* GetNSManagerWeakRef()
00309   {
00310     return sNameSpaceManager;
00311   }
00312 
00313   static nsIIOService* GetIOServiceWeakRef()
00314   {
00315     return sIOService;
00316   }
00317 
00318   static imgILoader* GetImgLoader()
00319   {
00320     return sImgLoader;
00321   }
00322 
00323 #ifdef MOZ_XTF
00324   static nsIXTFService* GetXTFServiceWeakRef();
00325 #endif
00326 
00327   static nsIScriptSecurityManager* GetSecurityManager()
00328   {
00329     return sSecurityManager;
00330   }
00331 
00332   static nsresult GenerateStateKey(nsIContent* aContent,
00333                                    nsIDocument* aDocument,
00334                                    nsIStatefulFrame::SpecialStateID aID,
00335                                    nsACString& aKey);
00336 
00342   static nsresult NewURIWithDocumentCharset(nsIURI** aResult,
00343                                             const nsAString& aSpec,
00344                                             nsIDocument* aDocument,
00345                                             nsIURI* aBaseURI);
00346 
00355   static PRBool BelongsInForm(nsIDOMHTMLFormElement *aForm,
00356                               nsIContent *aContent);
00357 
00358   static nsresult CheckQName(const nsAString& aQualifiedName,
00359                              PRBool aNamespaceAware = PR_TRUE);
00360 
00361   static nsresult SplitQName(nsIContent* aNamespaceResolver,
00362                              const nsAFlatString& aQName,
00363                              PRInt32 *aNamespace, nsIAtom **aLocalName);
00364 
00365   static nsresult LookupNamespaceURI(nsIContent* aNamespaceResolver,
00366                                      const nsAString& aNamespacePrefix,
00367                                      nsAString& aNamespaceURI);
00368 
00369   static nsresult GetNodeInfoFromQName(const nsAString& aNamespaceURI,
00370                                        const nsAString& aQualifiedName,
00371                                        nsNodeInfoManager* aNodeInfoManager,
00372                                        nsINodeInfo** aNodeInfo);
00373 
00374   static void SplitExpatName(const PRUnichar *aExpatName, nsIAtom **aPrefix,
00375                              nsIAtom **aTagName, PRInt32 *aNameSpaceID);
00376 
00377   static nsAdoptingCString GetCharPref(const char *aPref);
00378   static PRPackedBool GetBoolPref(const char *aPref,
00379                                   PRBool aDefault = PR_FALSE);
00380   static PRInt32 GetIntPref(const char *aPref, PRInt32 aDefault = 0);
00381   static nsAdoptingString GetLocalizedStringPref(const char *aPref);
00382   static nsAdoptingString GetStringPref(const char *aPref);
00383   static void RegisterPrefCallback(const char *aPref,
00384                                    PrefChangedFunc aCallback,
00385                                    void * aClosure);
00386   static void UnregisterPrefCallback(const char *aPref,
00387                                      PrefChangedFunc aCallback,
00388                                      void * aClosure);
00389   static nsIPrefBranch *GetPrefBranch()
00390   {
00391     return sPrefBranch;
00392   }
00393 
00394   static nsresult GetDocumentAndPrincipal(nsIDOMNode* aNode,
00395                                           nsIDocument** aDocument,
00396                                           nsIPrincipal** aPrincipal);
00397 
00413   static PRBool CanLoadImage(nsIURI* aURI,
00414                              nsISupports* aContext,
00415                              nsIDocument* aLoadingDocument,
00416                              PRInt16* aImageBlockingStatus = nsnull);
00426   static nsresult LoadImage(nsIURI* aURI,
00427                             nsIDocument* aLoadingDocument,
00428                             nsIURI* aReferrer,
00429                             imgIDecoderObserver* aObserver,
00430                             PRInt32 aLoadFlags,
00431                             imgIRequest** aRequest);
00432 
00440   static already_AddRefed<nsIImage> GetImageFromContent(nsIImageLoadingContent* aContent, imgIRequest **aRequest = nsnull);
00441 
00448   static PRBool ContentIsDraggable(nsIContent* aContent) {
00449     return IsDraggableImage(aContent) || IsDraggableLink(aContent);
00450   }
00451 
00458   static PRBool IsDraggableImage(nsIContent* aContent);
00459 
00466   static PRBool IsDraggableLink(nsIContent* aContent);
00467 
00475   static already_AddRefed<nsIURI> GetLinkURI(nsIContent* aContent);
00476 
00483   static already_AddRefed<nsIURI> GetXLinkURI(nsIContent* aContent);
00484 
00489   static nsresult NameChanged(nsINodeInfo *aNodeInfo, nsIAtom *aName,
00490                               nsINodeInfo** aResult)
00491   {
00492     nsNodeInfoManager *niMgr = aNodeInfo->NodeInfoManager();
00493 
00494     return niMgr->GetNodeInfo(aName, aNodeInfo->GetPrefixAtom(),
00495                               aNodeInfo->NamespaceID(), aResult);
00496   }
00497 
00502   static nsresult PrefixChanged(nsINodeInfo *aNodeInfo, nsIAtom *aPrefix,
00503                                 nsINodeInfo** aResult)
00504   {
00505     nsNodeInfoManager *niMgr = aNodeInfo->NodeInfoManager();
00506 
00507     return niMgr->GetNodeInfo(aNodeInfo->NameAtom(), aPrefix,
00508                               aNodeInfo->NamespaceID(), aResult);
00509   }
00510 
00514   static nsIDocument *GetDocument(nsINodeInfo *aNodeInfo)
00515   {
00516     return aNodeInfo->NodeInfoManager()->GetDocument();
00517   }
00518 
00524   static const char *GetEventArgName(PRInt32 aNameSpaceID);
00525 
00529   static nsIXPConnect *XPConnect()
00530   {
00531     return sXPConnect;
00532   }
00533 
00548   enum PropertiesFile {
00549     eCSS_PROPERTIES,
00550     eXBL_PROPERTIES,
00551     eXUL_PROPERTIES,
00552     eLAYOUT_PROPERTIES,
00553     eFORMS_PROPERTIES,
00554     ePRINTING_PROPERTIES,
00555     eDOM_PROPERTIES,
00556     eBRAND_PROPERTIES,
00557     PropertiesFile_COUNT
00558   };
00559   static nsresult ReportToConsole(PropertiesFile aFile,
00560                                   const char *aMessageName,
00561                                   const PRUnichar **aParams,
00562                                   PRUint32 aParamsLength,
00563                                   nsIURI* aURI,
00564                                   const nsAFlatString& aSourceLine,
00565                                   PRUint32 aLineNumber,
00566                                   PRUint32 aColumnNumber,
00567                                   PRUint32 aErrorFlags,
00568                                   const char *aCategory);
00569 
00573   static nsresult GetLocalizedString(PropertiesFile aFile,
00574                                      const char* aKey,
00575                                      nsXPIDLString& aResult);
00576 
00581   static nsresult FormatLocalizedString(PropertiesFile aFile,
00582                                         const char* aKey,
00583                                         const PRUnichar **aParams,
00584                                         PRUint32 aParamsLength,
00585                                         nsXPIDLString& aResult);
00586 
00591   static already_AddRefed<nsContentList>
00592   GetFormControlElements(nsIDocument *aDocument);
00593 
00597   static PRBool IsChromeDoc(nsIDocument *aDocument);
00598 
00602   static void NotifyXPCIfExceptionPending(JSContext *aCx);
00603 
00607   static nsresult ReleasePtrOnShutdown(nsISupports** aSupportsPtr) {
00608     NS_ASSERTION(aSupportsPtr, "Expect to crash!");
00609     NS_ASSERTION(*aSupportsPtr, "Expect to crash!");
00610     return sPtrsToPtrsToRelease->AppendElement(aSupportsPtr) ? NS_OK :
00611       NS_ERROR_OUT_OF_MEMORY;
00612   }
00618   static nsresult AddJSGCRoot(jsval* aPtr, const char* aName) {
00619     return AddJSGCRoot((void*)aPtr, aName);
00620   }
00621 
00627   static nsresult AddJSGCRoot(JSObject** aPtr, const char* aName) {
00628     return AddJSGCRoot((void*)aPtr, aName);
00629   }
00630 
00636   static nsresult AddJSGCRoot(void* aPtr, const char* aName);  
00637 
00641   static nsresult RemoveJSGCRoot(jsval* aPtr) {
00642     return RemoveJSGCRoot((void*)aPtr);
00643   }
00644   static nsresult RemoveJSGCRoot(JSObject** aPtr) {
00645     return RemoveJSGCRoot((void*)aPtr);
00646   }
00647   static nsresult RemoveJSGCRoot(void* aPtr);
00648 
00649   static PRBool IsNativeAnonymous(nsIContent* aContent);
00650   
00651 private:
00652   static nsresult doReparentContentWrapper(nsIContent *aChild,
00653                                            JSContext *cx,
00654                                            JSObject *aOldGlobal,
00655                                            JSObject *aNewGlobal);
00656 
00657   static nsresult EnsureStringBundle(PropertiesFile aFile);
00658 
00659 
00660   static nsIDOMScriptObjectFactory *sDOMScriptObjectFactory;
00661 
00662   static nsIXPConnect *sXPConnect;
00663 
00664   static nsIScriptSecurityManager *sSecurityManager;
00665 
00666   static nsIThreadJSContextStack *sThreadJSContextStack;
00667 
00668   static nsIParserService *sParserService;
00669 
00670   static nsINameSpaceManager *sNameSpaceManager;
00671 
00672   static nsIIOService *sIOService;
00673 
00674 #ifdef MOZ_XTF
00675   static nsIXTFService *sXTFService;
00676 #endif
00677 
00678   static nsIPrefBranch *sPrefBranch;
00679 
00680   static nsIPref *sPref;
00681 
00682   static imgILoader* sImgLoader;
00683 
00684   static nsIConsoleService* sConsoleService;
00685 
00686   static nsIStringBundleService* sStringBundleService;
00687   static nsIStringBundle* sStringBundles[PropertiesFile_COUNT];
00688 
00689   // Holds pointers to nsISupports* that should be released at shutdown
00690   static nsVoidArray* sPtrsToPtrsToRelease;
00691 
00692   // For now, we don't want to automatically clean this up in Shutdown(), since
00693   // consumers might unfortunately end up wanting to use it after that
00694   static nsIJSRuntimeService* sJSRuntimeService;
00695   static JSRuntime* sScriptRuntime;
00696   static PRInt32 sScriptRootCount;
00697   
00698   static PRBool sInitialized;
00699 };
00700 
00701 
00702 class nsCxPusher
00703 {
00704 public:
00705   nsCxPusher() : mScriptIsRunning(PR_FALSE) {}
00706   ~nsCxPusher() { Pop(); }
00707   // Returns PR_FALSE if something erroneous happened.
00708   PRBool Push(nsISupports *aCurrentTarget);
00709   void Pop();
00710 
00711 private:
00712   nsCOMPtr<nsIJSContextStack> mStack;
00713   nsCOMPtr<nsIScriptContext> mScx;
00714   PRBool mScriptIsRunning;
00715 };
00716 
00717 class nsAutoGCRoot {
00718 public:
00719   // aPtr should be the pointer to the jsval we want to protect
00720   nsAutoGCRoot(jsval* aPtr, nsresult* aResult) :
00721     mPtr(aPtr)
00722   {
00723     mResult = *aResult =
00724       nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
00725   }
00726 
00727   // aPtr should be the pointer to the JSObject* we want to protect
00728   nsAutoGCRoot(JSObject** aPtr, nsresult* aResult) :
00729     mPtr(aPtr)
00730   {
00731     mResult = *aResult =
00732       nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
00733   }
00734 
00735   // aPtr should be the pointer to the thing we want to protect
00736   nsAutoGCRoot(void* aPtr, nsresult* aResult) :
00737     mPtr(aPtr)
00738   {
00739     mResult = *aResult =
00740       nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
00741   }
00742 
00743   ~nsAutoGCRoot() {
00744     if (NS_SUCCEEDED(mResult)) {
00745       nsContentUtils::RemoveJSGCRoot(mPtr);
00746     }
00747   }
00748 
00749 private:
00750   void* mPtr;
00751   nsresult mResult;
00752 };
00753 
00754 #define NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(_class)                      \
00755   if (aIID.Equals(NS_GET_IID(nsIClassInfo))) {                                \
00756     foundInterface =                                                          \
00757       nsContentUtils::GetClassInfoInstance(eDOMClassInfo_##_class##_id);      \
00758     if (!foundInterface) {                                                    \
00759       *aInstancePtr = nsnull;                                                 \
00760       return NS_ERROR_OUT_OF_MEMORY;                                          \
00761     }                                                                         \
00762   } else
00763 
00764 #define NS_INTERFACE_MAP_ENTRY_TEAROFF(_interface, _allocator)                \
00765   if (aIID.Equals(NS_GET_IID(_interface))) {                                  \
00766     foundInterface = NS_STATIC_CAST(_interface *, _allocator);                \
00767     if (!foundInterface) {                                                    \
00768       *aInstancePtr = nsnull;                                                 \
00769       return NS_ERROR_OUT_OF_MEMORY;                                          \
00770     }                                                                         \
00771   } else
00772 
00773 #endif /* nsContentUtils_h___ */