Back to index

lightning-sunbird  0.9+nobinonly
nsXTFElementWrapper.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Mozilla XTF project.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Alex Fritze.
00019  * Portions created by the Initial Developer are Copyright (C) 2004
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Alex Fritze <alex@croczilla.com> (original author)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * 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 #include "nsXTFElementWrapper.h"
00040 #include "nsIXTFElement.h"
00041 #include "nsCOMPtr.h"
00042 #include "nsString.h"
00043 #include "nsXTFInterfaceAggregator.h"
00044 #include "nsIClassInfo.h"
00045 #include "nsPIDOMWindow.h"
00046 #include "nsIInterfaceRequestorUtils.h"
00047 #include "nsIDocument.h"
00048 #include "nsHTMLAtoms.h" // XXX only needed for nsHTMLAtoms::id
00049 #include "nsIEventListenerManager.h"
00050 #include "nsIDOMEvent.h"
00051 #include "nsGUIEvent.h"
00052 #include "nsContentUtils.h"
00053 #include "nsIXTFService.h"
00054 #include "nsDOMAttributeMap.h"
00055 
00056 nsXTFElementWrapper::nsXTFElementWrapper(nsINodeInfo* aNodeInfo)
00057     : nsXTFElementWrapperBase(aNodeInfo),
00058       mNotificationMask(0),
00059       mIntrinsicState(0)
00060 {
00061 }
00062 
00063 nsresult
00064 nsXTFElementWrapper::Init()
00065 {
00066   PRBool innerHandlesAttribs = PR_FALSE;
00067   GetXTFElement()->GetIsAttributeHandler(&innerHandlesAttribs);
00068   if (innerHandlesAttribs)
00069     mAttributeHandler = do_QueryInterface(GetXTFElement());
00070   return NS_OK;
00071 }
00072 
00073 //----------------------------------------------------------------------
00074 // nsISupports implementation
00075 
00076 NS_IMPL_ADDREF_INHERITED(nsXTFElementWrapper,nsXTFElementWrapperBase)
00077 NS_IMPL_RELEASE_INHERITED(nsXTFElementWrapper,nsXTFElementWrapperBase)
00078 
00079 NS_IMETHODIMP
00080 nsXTFElementWrapper::QueryInterface(REFNSIID aIID, void** aInstancePtr)
00081 {
00082   nsresult rv;
00083   
00084   if(aIID.Equals(NS_GET_IID(nsIClassInfo))) {
00085     *aInstancePtr = NS_STATIC_CAST(nsIClassInfo*, this);
00086     NS_ADDREF_THIS();
00087     return NS_OK;
00088   }
00089   else if (aIID.Equals(NS_GET_IID(nsIXTFElementWrapperPrivate))) {
00090     *aInstancePtr = NS_STATIC_CAST(nsIXTFElementWrapperPrivate*, this);
00091     NS_ADDREF_THIS();
00092     return NS_OK;
00093   }
00094   else if(aIID.Equals(NS_GET_IID(nsIXTFElementWrapper))) {
00095     *aInstancePtr = NS_STATIC_CAST(nsIXTFElementWrapper*, this);
00096     NS_ADDREF_THIS();
00097     return NS_OK;
00098   }
00099   else if (NS_SUCCEEDED(rv = nsXTFElementWrapperBase::QueryInterface(aIID, aInstancePtr))) {
00100     return rv;
00101   }
00102   else {
00103     // try to get get the interface from our wrapped element:
00104     nsCOMPtr<nsISupports> inner;
00105     QueryInterfaceInner(aIID, getter_AddRefs(inner));
00106 
00107     if (inner) {
00108       rv = NS_NewXTFInterfaceAggregator(aIID, inner,
00109                                         NS_STATIC_CAST(nsIContent*, this),
00110                                         aInstancePtr);
00111 
00112       return rv;
00113     }
00114   }
00115 
00116   return NS_ERROR_NO_INTERFACE;
00117 }
00118 
00119 //----------------------------------------------------------------------
00120 // nsIContent methods:
00121 
00122 nsresult
00123 nsXTFElementWrapper::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
00124                                 nsIContent* aBindingParent,
00125                                 PRBool aCompileEventHandlers)
00126 {
00127   // XXXbz making up random order for the notifications... Perhaps
00128   // this api should more closely match BindToTree/UnbindFromTree?
00129   nsCOMPtr<nsIDOMElement> domParent;
00130   if (aParent != GetParent()) {
00131     domParent = do_QueryInterface(aParent);
00132   }
00133 
00134   nsCOMPtr<nsIDOMDocument> domDocument;
00135   if (aDocument &&
00136       (mNotificationMask & (nsIXTFElement::NOTIFY_WILL_CHANGE_DOCUMENT |
00137                             nsIXTFElement::NOTIFY_DOCUMENT_CHANGED))) {
00138     domDocument = do_QueryInterface(aDocument);
00139   }
00140 
00141   if (domDocument &&
00142       (mNotificationMask & (nsIXTFElement::NOTIFY_WILL_CHANGE_DOCUMENT))) {
00143     GetXTFElement()->WillChangeDocument(domDocument);
00144   }
00145 
00146   if (domParent &&
00147       (mNotificationMask & (nsIXTFElement::NOTIFY_WILL_CHANGE_PARENT))) {
00148     GetXTFElement()->WillChangeParent(domParent);
00149   }
00150 
00151   nsresult rv = nsXTFElementWrapperBase::BindToTree(aDocument, aParent,
00152                                                     aBindingParent,
00153                                                     aCompileEventHandlers);
00154 
00155   NS_ENSURE_SUCCESS(rv, rv);
00156 
00157   if (domDocument &&
00158       (mNotificationMask & (nsIXTFElement::NOTIFY_DOCUMENT_CHANGED))) {
00159     GetXTFElement()->DocumentChanged(domDocument);
00160   }
00161 
00162   if (domParent &&
00163       (mNotificationMask & (nsIXTFElement::NOTIFY_PARENT_CHANGED))) {
00164     GetXTFElement()->ParentChanged(domParent);
00165   }
00166 
00167   return rv;  
00168 }
00169 
00170 void
00171 nsXTFElementWrapper::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
00172 {
00173   // XXXbz making up random order for the notifications... Perhaps
00174   // this api should more closely match BindToTree/UnbindFromTree?
00175   PRBool inDoc = IsInDoc();
00176   if (inDoc &&
00177       (mNotificationMask & nsIXTFElement::NOTIFY_WILL_CHANGE_DOCUMENT)) {
00178     GetXTFElement()->WillChangeDocument(nsnull);
00179   }
00180 
00181   PRBool parentChanged = aNullParent && GetParent();
00182 
00183   if (parentChanged &&
00184       (mNotificationMask & nsIXTFElement::NOTIFY_WILL_CHANGE_PARENT)) {
00185     GetXTFElement()->WillChangeParent(nsnull);
00186   }
00187 
00188   nsXTFElementWrapperBase::UnbindFromTree(aDeep, aNullParent);
00189 
00190   if (parentChanged &&
00191       (mNotificationMask & nsIXTFElement::NOTIFY_PARENT_CHANGED)) {
00192     GetXTFElement()->ParentChanged(nsnull);
00193   }
00194 
00195   if (inDoc &&
00196       (mNotificationMask & nsIXTFElement::NOTIFY_DOCUMENT_CHANGED)) {
00197     GetXTFElement()->DocumentChanged(nsnull);
00198   }
00199 }
00200 
00201 nsresult
00202 nsXTFElementWrapper::InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
00203                                    PRBool aNotify)
00204 {
00205   nsresult rv;
00206 
00207   nsCOMPtr<nsIDOMNode> domKid;
00208   if (mNotificationMask & (nsIXTFElement::NOTIFY_WILL_INSERT_CHILD |
00209                            nsIXTFElement::NOTIFY_CHILD_INSERTED))
00210     domKid = do_QueryInterface(aKid);
00211   
00212   if (mNotificationMask & nsIXTFElement::NOTIFY_WILL_INSERT_CHILD)
00213     GetXTFElement()->WillInsertChild(domKid, aIndex);
00214   rv = nsXTFElementWrapperBase::InsertChildAt(aKid, aIndex, aNotify);
00215   if (mNotificationMask & nsIXTFElement::NOTIFY_CHILD_INSERTED)
00216     GetXTFElement()->ChildInserted(domKid, aIndex);
00217   
00218   return rv;
00219 }
00220 
00221 nsresult
00222 nsXTFElementWrapper::AppendChildTo(nsIContent* aKid, PRBool aNotify)
00223 {
00224   nsresult rv;
00225 
00226   nsCOMPtr<nsIDOMNode> domKid;
00227   if (mNotificationMask & (nsIXTFElement::NOTIFY_WILL_APPEND_CHILD |
00228                            nsIXTFElement::NOTIFY_CHILD_APPENDED))
00229     domKid = do_QueryInterface(aKid);
00230   
00231   if (mNotificationMask & nsIXTFElement::NOTIFY_WILL_APPEND_CHILD)
00232     GetXTFElement()->WillAppendChild(domKid);
00233   rv = nsXTFElementWrapperBase::AppendChildTo(aKid, aNotify);
00234   if (mNotificationMask & nsIXTFElement::NOTIFY_CHILD_APPENDED)
00235     GetXTFElement()->ChildAppended(domKid);
00236   return rv;
00237 }
00238 
00239 nsresult
00240 nsXTFElementWrapper::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
00241 {
00242   nsresult rv;
00243   if (mNotificationMask & nsIXTFElement::NOTIFY_WILL_REMOVE_CHILD)
00244     GetXTFElement()->WillRemoveChild(aIndex);
00245   rv = nsXTFElementWrapperBase::RemoveChildAt(aIndex, aNotify);
00246   if (mNotificationMask & nsIXTFElement::NOTIFY_CHILD_REMOVED)
00247     GetXTFElement()->ChildRemoved(aIndex);
00248   return rv;
00249 }
00250 
00251 nsIAtom *
00252 nsXTFElementWrapper::GetIDAttributeName() const
00253 {
00254   // XXX:
00255   return nsHTMLAtoms::id;
00256 }
00257 
00258 nsresult
00259 nsXTFElementWrapper::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
00260                              nsIAtom* aPrefix, const nsAString& aValue,
00261                              PRBool aNotify)
00262 {
00263   nsresult rv;
00264   
00265   if (mNotificationMask & nsIXTFElement::NOTIFY_WILL_SET_ATTRIBUTE)
00266     GetXTFElement()->WillSetAttribute(aName, aValue);
00267 
00268   if (aNameSpaceID==kNameSpaceID_None && HandledByInner(aName)) {
00269     // XXX we don't do namespaced attributes yet
00270     if (aNameSpaceID != kNameSpaceID_None) {
00271       NS_WARNING("setattr: xtf elements don't do namespaced attribs yet!");
00272       return NS_ERROR_FAILURE;
00273     }  
00274     rv = mAttributeHandler->SetAttribute(aName, aValue);
00275     // XXX mutation events?
00276   }
00277   else { // let wrapper handle it
00278     rv = nsXTFElementWrapperBase::SetAttr(aNameSpaceID, aName, aPrefix, aValue, aNotify);
00279   }
00280   
00281   if (mNotificationMask & nsIXTFElement::NOTIFY_ATTRIBUTE_SET)
00282     GetXTFElement()->AttributeSet(aName, aValue);
00283   
00284   return rv;
00285 }
00286 
00287 nsresult
00288 nsXTFElementWrapper::GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, 
00289                              nsAString& aResult) const
00290 {
00291   if (aNameSpaceID==kNameSpaceID_None && HandledByInner(aName)) {
00292     // XXX we don't do namespaced attributes yet
00293     if (aNameSpaceID != kNameSpaceID_None) {
00294       NS_WARNING("getattr: xtf elements don't do namespaced attribs yet!");
00295       return NS_CONTENT_ATTR_NOT_THERE;
00296     }
00297     nsresult rv = mAttributeHandler->GetAttribute(aName, aResult);
00298     if (NS_FAILED(rv)) return rv;
00299     if (aResult.IsVoid()) return NS_CONTENT_ATTR_NOT_THERE;
00300     if (aResult.IsEmpty()) return NS_CONTENT_ATTR_NO_VALUE;
00301     
00302     return NS_CONTENT_ATTR_HAS_VALUE;
00303   }
00304   else { // try wrapper
00305     return nsXTFElementWrapperBase::GetAttr(aNameSpaceID, aName, aResult);
00306   }
00307 }
00308 
00309 PRBool
00310 nsXTFElementWrapper::HasAttr(PRInt32 aNameSpaceID, nsIAtom* aName) const
00311 {
00312   if (aNameSpaceID==kNameSpaceID_None && HandledByInner(aName)) {
00313     PRBool rval = PR_FALSE;
00314     mAttributeHandler->HasAttribute(aName, &rval);
00315     return rval;
00316   }
00317   else { // try wrapper
00318     return nsXTFElementWrapperBase::HasAttr(aNameSpaceID, aName);
00319   }
00320 }
00321 
00322 
00323 nsresult
00324 nsXTFElementWrapper::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttr, 
00325                                PRBool aNotify)
00326 {
00327   nsresult rv;
00328 
00329   if (mNotificationMask & nsIXTFElement::NOTIFY_WILL_REMOVE_ATTRIBUTE)
00330     GetXTFElement()->WillRemoveAttribute(aAttr);
00331   
00332   if (aNameSpaceID==kNameSpaceID_None && HandledByInner(aAttr)) {
00333     // XXX we don't do namespaced attributes yet
00334     if (aNameSpaceID != kNameSpaceID_None) {
00335       NS_WARNING("setattr: xtf elements don't do namespaced attribs yet!");
00336       return NS_ERROR_FAILURE;
00337     }  
00338     nsDOMSlots *slots = GetExistingDOMSlots();
00339     if (slots && slots->mAttributeMap) {
00340       slots->mAttributeMap->DropAttribute(aNameSpaceID, aAttr);
00341     }
00342     rv = mAttributeHandler->RemoveAttribute(aAttr);
00343 
00344     // XXX if the RemoveAttribute() call fails, we might end up having removed
00345     // the attribute from the attribute map even though the attribute is still
00346     // on the element
00347     // https://bugzilla.mozilla.org/show_bug.cgi?id=296205
00348 
00349     // XXX mutation events?
00350   }
00351   else { // try wrapper
00352     rv = nsXTFElementWrapperBase::UnsetAttr(aNameSpaceID, aAttr, aNotify);
00353   }
00354 
00355   if (mNotificationMask & nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED)
00356     GetXTFElement()->AttributeRemoved(aAttr);
00357 
00358   return rv;
00359 }
00360 
00361 nsresult
00362 nsXTFElementWrapper::GetAttrNameAt(PRUint32 aIndex, PRInt32* aNameSpaceID,
00363                                    nsIAtom** aName, nsIAtom** aPrefix) const
00364 {
00365   PRUint32 innerCount=0;
00366   if (mAttributeHandler) {
00367     mAttributeHandler->GetAttributeCount(&innerCount);
00368   }
00369   
00370   if (aIndex < innerCount) {
00371     *aNameSpaceID = kNameSpaceID_None;
00372     *aPrefix = nsnull;
00373     return mAttributeHandler->GetAttributeNameAt(aIndex, aName);
00374   }
00375   else { // wrapper handles attrib
00376     return nsXTFElementWrapperBase::GetAttrNameAt(aIndex - innerCount, aNameSpaceID,
00377                                                   aName, aPrefix);
00378   }
00379 }
00380 
00381 PRUint32
00382 nsXTFElementWrapper::GetAttrCount() const
00383 {
00384   PRUint32 innerCount = 0;
00385   if (mAttributeHandler) {
00386     mAttributeHandler->GetAttributeCount(&innerCount);
00387   }
00388   // add wrapper attribs
00389   return innerCount + nsXTFElementWrapperBase::GetAttrCount();
00390 }
00391 
00392 void
00393 nsXTFElementWrapper::BeginAddingChildren()
00394 {
00395   if (mNotificationMask & nsIXTFElement::NOTIFY_BEGIN_ADDING_CHILDREN)
00396     GetXTFElement()->BeginAddingChildren();
00397 }
00398 
00399 void
00400 nsXTFElementWrapper::DoneAddingChildren()
00401 {
00402   if (mNotificationMask & nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN)
00403     GetXTFElement()->DoneAddingChildren();
00404 }
00405 
00406 already_AddRefed<nsINodeInfo>
00407 nsXTFElementWrapper::GetExistingAttrNameFromQName(const nsAString& aStr) const
00408 {
00409   nsINodeInfo* nodeInfo = nsXTFElementWrapperBase::GetExistingAttrNameFromQName(aStr).get();
00410 
00411   // Maybe this attribute is handled by our inner element:
00412   if (!nodeInfo) {
00413     nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aStr);
00414     if (HandledByInner(nameAtom)) 
00415       mNodeInfo->NodeInfoManager()->GetNodeInfo(nameAtom, nsnull, kNameSpaceID_None, &nodeInfo);
00416   }
00417   
00418   return nodeInfo;
00419 }
00420 
00421 PRInt32
00422 nsXTFElementWrapper::IntrinsicState() const
00423 {
00424   return mIntrinsicState;
00425 }
00426 
00427 //----------------------------------------------------------------------
00428 // nsIDOMNode methods:
00429 
00430 NS_IMETHODIMP
00431 nsXTFElementWrapper::CloneNode(PRBool aDeep, nsIDOMNode **aResult)
00432 {
00433   *aResult = nsnull;
00434   nsCOMPtr<nsIContent> it;
00435   nsContentUtils::GetXTFServiceWeakRef()->CreateElement(getter_AddRefs(it),
00436                                                         mNodeInfo);
00437   if (!it)
00438     return NS_ERROR_OUT_OF_MEMORY;
00439 
00440   nsCOMPtr<nsIDOMNode> kungFuDeathGrip(do_QueryInterface(it));
00441   nsXTFElementWrapper* wrapper =
00442     NS_STATIC_CAST(nsXTFElementWrapper*, NS_STATIC_CAST(nsIContent*, it.get()));
00443   nsresult rv = CopyInnerTo(wrapper, aDeep);
00444 
00445   if (NS_SUCCEEDED(rv)) {
00446     if (mAttributeHandler) {
00447       PRUint32 innerCount = 0;
00448       mAttributeHandler->GetAttributeCount(&innerCount);
00449       for (PRUint32 i = 0; i < innerCount; ++i) {
00450         nsCOMPtr<nsIAtom> attrName;
00451         mAttributeHandler->GetAttributeNameAt(i, getter_AddRefs(attrName));
00452         if (attrName) {
00453           nsAutoString value;
00454           if (NS_SUCCEEDED(mAttributeHandler->GetAttribute(attrName, value)))
00455             it->SetAttr(kNameSpaceID_None, attrName, value, PR_TRUE);
00456         }
00457       }
00458     }
00459     kungFuDeathGrip.swap(*aResult);
00460   }
00461 
00462   wrapper->CloneState(this);
00463   return rv;
00464 }
00465 
00466 //----------------------------------------------------------------------
00467 // nsIDOMElement methods:
00468 
00469 NS_IMETHODIMP
00470 nsXTFElementWrapper::GetAttribute(const nsAString& aName, nsAString& aReturn)
00471 {
00472   const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
00473   if (name) {
00474     GetAttr(name->NamespaceID(), name->LocalName(), aReturn);
00475     return NS_OK;
00476   }
00477 
00478   // Maybe this attribute is handled by our inner element:
00479   if (mAttributeHandler) {
00480     nsresult rv = nsContentUtils::CheckQName(aName, PR_FALSE);
00481     NS_ENSURE_SUCCESS(rv, rv);
00482     nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
00483     if (HandledByInner(nameAtom)) {
00484       GetAttr(kNameSpaceID_None, nameAtom, aReturn);
00485       return NS_OK;
00486     }
00487   }
00488   
00489   SetDOMStringToNull(aReturn);
00490   return NS_OK;
00491 }
00492 
00493 NS_IMETHODIMP
00494 nsXTFElementWrapper::RemoveAttribute(const nsAString& aName)
00495 {
00496   const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
00497 
00498   if (name) {
00499     nsAttrName tmp(*name);
00500     return UnsetAttr(name->NamespaceID(), name->LocalName(), PR_TRUE);
00501   }
00502 
00503   // Maybe this attribute is handled by our inner element:
00504   if (mAttributeHandler) {
00505     nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
00506     return UnsetAttr(kNameSpaceID_None, nameAtom, PR_TRUE);
00507   }
00508 
00509   return NS_OK;
00510 }
00511 
00512 NS_IMETHODIMP
00513 nsXTFElementWrapper::HasAttribute(const nsAString& aName, PRBool* aReturn)
00514 {
00515   const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
00516   if (name) {
00517     *aReturn = PR_TRUE;
00518     return NS_OK;
00519   }
00520   
00521   // Maybe this attribute is handled by our inner element:
00522   if (mAttributeHandler) {
00523     nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
00524     *aReturn = HasAttr(kNameSpaceID_None, nameAtom);
00525     return NS_OK;
00526   }
00527 
00528   *aReturn = PR_FALSE;
00529   return NS_OK;
00530 }
00531 
00532 
00533 //----------------------------------------------------------------------
00534 // nsIClassInfo implementation
00535 
00536 /* void getInterfaces (out PRUint32 count, [array, size_is (count), retval] out nsIIDPtr array); */
00537 NS_IMETHODIMP 
00538 nsXTFElementWrapper::GetInterfaces(PRUint32 *count, nsIID * **array)
00539 {
00540   return GetXTFElement()->GetScriptingInterfaces(count, array);
00541 }
00542 
00543 /* nsISupports getHelperForLanguage (in PRUint32 language); */
00544 NS_IMETHODIMP 
00545 nsXTFElementWrapper::GetHelperForLanguage(PRUint32 language,
00546                                           nsISupports** aHelper)
00547 {
00548   *aHelper = nsnull;
00549   nsCOMPtr<nsIClassInfo> ci = 
00550     do_QueryInterface(nsContentUtils::GetClassInfoInstance(eDOMClassInfo_Element_id));
00551   return
00552     ci ? ci->GetHelperForLanguage(language, aHelper) : NS_ERROR_NOT_AVAILABLE;
00553 }
00554 
00555 /* readonly attribute string contractID; */
00556 NS_IMETHODIMP 
00557 nsXTFElementWrapper::GetContractID(char * *aContractID)
00558 {
00559   *aContractID = nsnull;
00560   return NS_OK;
00561 }
00562 
00563 /* readonly attribute string classDescription; */
00564 NS_IMETHODIMP 
00565 nsXTFElementWrapper::GetClassDescription(char * *aClassDescription)
00566 {
00567   *aClassDescription = nsnull;
00568   return NS_OK;
00569 }
00570 
00571 /* readonly attribute nsCIDPtr classID; */
00572 NS_IMETHODIMP 
00573 nsXTFElementWrapper::GetClassID(nsCID * *aClassID)
00574 {
00575   *aClassID = nsnull;
00576   return NS_OK;
00577 }
00578 
00579 /* readonly attribute PRUint32 implementationLanguage; */
00580 NS_IMETHODIMP 
00581 nsXTFElementWrapper::GetImplementationLanguage(PRUint32 *aImplementationLanguage)
00582 {
00583   *aImplementationLanguage = nsIProgrammingLanguage::UNKNOWN;
00584   return NS_OK;
00585 }
00586 
00587 /* readonly attribute PRUint32 flags; */
00588 NS_IMETHODIMP 
00589 nsXTFElementWrapper::GetFlags(PRUint32 *aFlags)
00590 {
00591   *aFlags = nsIClassInfo::DOM_OBJECT;
00592   return NS_OK;
00593 }
00594 
00595 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
00596 NS_IMETHODIMP 
00597 nsXTFElementWrapper::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
00598 {
00599   return NS_ERROR_NOT_AVAILABLE;
00600 }
00601 
00602 //----------------------------------------------------------------------
00603 // nsIXTFElementWrapper implementation:
00604 
00605 /* readonly attribute nsIDOMElement elementNode; */
00606 NS_IMETHODIMP
00607 nsXTFElementWrapper::GetElementNode(nsIDOMElement * *aElementNode)
00608 {
00609   *aElementNode = (nsIDOMElement*)this;
00610   NS_ADDREF(*aElementNode);
00611   return NS_OK;
00612 }
00613 
00614 /* readonly attribute nsIDOMElement documentFrameElement; */
00615 NS_IMETHODIMP
00616 nsXTFElementWrapper::GetDocumentFrameElement(nsIDOMElement * *aDocumentFrameElement)
00617 {
00618   *aDocumentFrameElement = nsnull;
00619   
00620   nsIDocument *doc = GetCurrentDoc();
00621   if (!doc) {
00622     NS_WARNING("no document");
00623     return NS_OK;
00624   }
00625   nsCOMPtr<nsISupports> container = doc->GetContainer();
00626   if (!container) {
00627     NS_ERROR("no docshell");
00628     return NS_ERROR_FAILURE;
00629   }
00630   nsCOMPtr<nsPIDOMWindow> pidomwin = do_GetInterface(container);
00631   if (!pidomwin) {
00632     NS_ERROR("no nsPIDOMWindow interface on docshell");
00633     return NS_ERROR_FAILURE;
00634   }
00635   *aDocumentFrameElement = pidomwin->GetFrameElementInternal();
00636   NS_IF_ADDREF(*aDocumentFrameElement);
00637   return NS_OK;
00638 }
00639 
00640 /* attribute unsigned long notificationMask; */
00641 NS_IMETHODIMP
00642 nsXTFElementWrapper::GetNotificationMask(PRUint32 *aNotificationMask)
00643 {
00644   *aNotificationMask = mNotificationMask;
00645   return NS_OK;
00646 }
00647 NS_IMETHODIMP
00648 nsXTFElementWrapper::SetNotificationMask(PRUint32 aNotificationMask)
00649 {
00650   mNotificationMask = aNotificationMask;
00651   return NS_OK;
00652 }
00653 
00654 //----------------------------------------------------------------------
00655 // implementation helpers:
00656 PRBool
00657 nsXTFElementWrapper::QueryInterfaceInner(REFNSIID aIID, void** result)
00658 {
00659   // We must ensure that the inner element has a distinct xpconnect
00660   // identity, so we mustn't aggregate nsIXPConnectWrappedJS:
00661   if (aIID.Equals(NS_GET_IID(nsIXPConnectWrappedJS))) return PR_FALSE;
00662 
00663   GetXTFElement()->QueryInterface(aIID, result);
00664   return (*result!=nsnull);
00665 }
00666 
00667 PRBool
00668 nsXTFElementWrapper::HandledByInner(nsIAtom *attr) const
00669 {
00670   PRBool retval = PR_FALSE;
00671   if (mAttributeHandler)
00672     mAttributeHandler->HandlesAttribute(attr, &retval);
00673   return retval;
00674 }
00675 
00676 nsresult
00677 nsXTFElementWrapper::HandleDOMEvent(nsPresContext* aPresContext,
00678                                     nsEvent* aEvent,
00679                                     nsIDOMEvent** aDOMEvent,
00680                                     PRUint32 aFlags,
00681                                     nsEventStatus* aEventStatus)
00682 {
00683   nsresult rv = nsXTFElementWrapperBase::HandleDOMEvent(aPresContext, aEvent,
00684                                                         aDOMEvent, aFlags,
00685                                                         aEventStatus);
00686 
00687   if (NS_FAILED(rv) ||
00688       (nsEventStatus_eIgnore != *aEventStatus) ||
00689       !(mNotificationMask & nsIXTFElement::NOTIFY_HANDLE_DEFAULT) ||
00690       (aFlags & (NS_EVENT_FLAG_SYSTEM_EVENT | NS_EVENT_FLAG_CAPTURE)))
00691     return rv;
00692 
00693   nsIDOMEvent* domEvent = nsnull;
00694   if (!aDOMEvent)
00695     aDOMEvent = &domEvent;
00696 
00697   if (!*aDOMEvent) {
00698     // We haven't made a DOMEvent yet.  Force making one now.
00699     nsCOMPtr<nsIEventListenerManager> listenerManager;
00700     if (NS_FAILED(rv = GetListenerManager(getter_AddRefs(listenerManager))))
00701       return rv;
00702 
00703     nsAutoString empty;
00704     if (NS_FAILED(rv = listenerManager->CreateEvent(aPresContext, aEvent,
00705                                                     empty, aDOMEvent)))
00706       return rv;
00707   }
00708   if (!*aDOMEvent)
00709     return NS_ERROR_FAILURE;
00710   
00711   PRBool defaultHandled = PR_FALSE;
00712   nsIXTFElement * xtfElement = GetXTFElement();
00713   if (xtfElement)
00714     rv = xtfElement->HandleDefault(*aDOMEvent, &defaultHandled);
00715   if (defaultHandled)
00716     *aEventStatus = nsEventStatus_eConsumeNoDefault;
00717   return rv;
00718 }
00719 
00720 NS_IMETHODIMP
00721 nsXTFElementWrapper::SetIntrinsicState(PRInt32 aNewState)
00722 {
00723   nsIDocument *doc = GetCurrentDoc();
00724   PRInt32 bits = mIntrinsicState ^ aNewState;
00725   
00726   if (!doc || !bits)
00727     return NS_OK;
00728 
00729   mIntrinsicState = aNewState;
00730   mozAutoDocUpdate(doc, UPDATE_CONTENT_STATE, PR_TRUE);
00731   doc->ContentStatesChanged(this, nsnull, bits);
00732 
00733   return NS_OK;
00734 }
00735 
00736 // nsXTFStyleableElementWrapper
00737 
00738 nsXTFStyledElementWrapper::nsXTFStyledElementWrapper(nsINodeInfo* aNodeInfo)
00739 : nsXTFElementWrapper(aNodeInfo)
00740 {
00741 }
00742 
00743 nsIAtom *
00744 nsXTFStyledElementWrapper::GetClassAttributeName() const
00745 {
00746   return mClassAttributeName;
00747 }
00748 
00749 const nsAttrValue*
00750 nsXTFStyledElementWrapper::GetClasses() const
00751 {
00752   const nsAttrValue* val = nsnull;
00753   nsIAtom* clazzAttr = GetClassAttributeName();
00754   if (clazzAttr) {
00755     val = mAttrsAndChildren.GetAttr(clazzAttr);
00756     // This is possibly the first time we need any classes.
00757     if (val && val->Type() == nsAttrValue::eString) {
00758       nsAutoString value;
00759       val->ToString(value);
00760       nsAttrValue newValue;
00761       newValue.ParseAtomArray(value);
00762       NS_CONST_CAST(nsAttrAndChildArray*, &mAttrsAndChildren)->
00763         SetAndTakeAttr(clazzAttr, newValue);
00764     }
00765   }
00766   return val;
00767 }
00768 
00769 PRBool
00770 nsXTFStyledElementWrapper::HasClass(nsIAtom* aClass, PRBool /*aCaseSensitive*/) const
00771 {
00772   const nsAttrValue* val = GetClasses();
00773   if (val) {
00774     if (val->Type() == nsAttrValue::eAtom) {
00775       return aClass == val->GetAtomValue();
00776     }
00777 
00778     if (val->Type() == nsAttrValue::eAtomArray) {
00779       return val->GetAtomArrayValue()->IndexOf(aClass) >= 0;
00780     }
00781   }
00782   return PR_FALSE;
00783 }
00784 
00785 nsresult
00786 nsXTFStyledElementWrapper::SetClassAttributeName(nsIAtom* aName)
00787 {
00788   // The class attribute name can be set only once
00789   if (mClassAttributeName || !aName)
00790     return NS_ERROR_FAILURE;
00791   
00792   mClassAttributeName = aName;
00793   return NS_OK;
00794 }