LCOV - code coverage report
Current view: directory - content/xul/content/src - nsXULElement.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1371 167 12.2 %
Date: 2012-06-02 Functions: 208 38 18.3 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Chris Waterson <waterson@netscape.com>
      24                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      25                 :  *   Peter Annema <disttsc@bart.nl>
      26                 :  *   Brendan Eich <brendan@mozilla.org>
      27                 :  *   Mike Shaver <shaver@mozilla.org>
      28                 :  *   Mark Hammond <mhammond@skippinet.com.au>
      29                 :  *
      30                 :  * Alternatively, the contents of this file may be used under the terms of
      31                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      32                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      33                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      34                 :  * of those above. If you wish to allow use of your version of this file only
      35                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      36                 :  * use your version of this file under the terms of the MPL, indicate your
      37                 :  * decision by deleting the provisions above and replace them with the notice
      38                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      39                 :  * the provisions above, a recipient may use your version of this file under
      40                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      41                 :  *
      42                 :  * ***** END LICENSE BLOCK *****
      43                 :  *
      44                 :  * This Original Code has been modified by IBM Corporation.
      45                 :  * Modifications made by IBM described herein are
      46                 :  * Copyright (c) International Business Machines
      47                 :  * Corporation, 2000
      48                 :  *
      49                 :  * Modifications to Mozilla code or documentation
      50                 :  * identified per MPL Section 3.3
      51                 :  *
      52                 :  * Date         Modified by     Description of modification
      53                 :  * 03/27/2000   IBM Corp.       Added PR_CALLBACK for Optlink
      54                 :  *                               use in OS2
      55                 :  */
      56                 : 
      57                 : #include "nsCOMPtr.h"
      58                 : #include "nsDOMCID.h"
      59                 : #include "nsDOMError.h"
      60                 : #include "nsDOMString.h"
      61                 : #include "nsIDOMEvent.h"
      62                 : #include "nsIPrivateDOMEvent.h"
      63                 : #include "nsHashtable.h"
      64                 : #include "nsIAtom.h"
      65                 : #include "nsIBaseWindow.h"
      66                 : #include "nsIDOMAttr.h"
      67                 : #include "nsIDOMDocument.h"
      68                 : #include "nsIDOMElement.h"
      69                 : #include "nsIDOMEventListener.h"
      70                 : #include "nsIDOMNodeList.h"
      71                 : #include "nsIDOMXULCommandDispatcher.h"
      72                 : #include "nsIDOMXULElement.h"
      73                 : #include "nsIDOMElementCSSInlineStyle.h"
      74                 : #include "nsIDOMXULSelectCntrlItemEl.h"
      75                 : #include "nsIDocument.h"
      76                 : #include "nsEventListenerManager.h"
      77                 : #include "nsEventStateManager.h"
      78                 : #include "nsFocusManager.h"
      79                 : #include "nsHTMLStyleSheet.h"
      80                 : #include "nsINameSpaceManager.h"
      81                 : #include "nsIObjectInputStream.h"
      82                 : #include "nsIObjectOutputStream.h"
      83                 : #include "nsIPresShell.h"
      84                 : #include "nsIPrincipal.h"
      85                 : #include "nsIRDFCompositeDataSource.h"
      86                 : #include "nsIRDFNode.h"
      87                 : #include "nsIRDFService.h"
      88                 : #include "nsIScriptContext.h"
      89                 : #include "nsIScriptRuntime.h"
      90                 : #include "nsIScriptGlobalObject.h"
      91                 : #include "nsIScriptGlobalObjectOwner.h"
      92                 : #include "nsIServiceManager.h"
      93                 : #include "mozilla/css/StyleRule.h"
      94                 : #include "nsIStyleSheet.h"
      95                 : #include "nsIURL.h"
      96                 : #include "nsIViewManager.h"
      97                 : #include "nsIWidget.h"
      98                 : #include "nsIXULDocument.h"
      99                 : #include "nsIXULTemplateBuilder.h"
     100                 : #include "nsIXBLService.h"
     101                 : #include "nsLayoutCID.h"
     102                 : #include "nsContentCID.h"
     103                 : #include "nsRDFCID.h"
     104                 : #include "nsStyleConsts.h"
     105                 : #include "nsXPIDLString.h"
     106                 : #include "nsXULControllers.h"
     107                 : #include "nsIBoxObject.h"
     108                 : #include "nsPIBoxObject.h"
     109                 : #include "nsXULDocument.h"
     110                 : #include "nsXULPopupListener.h"
     111                 : #include "nsRuleWalker.h"
     112                 : #include "nsIDOMCSSStyleDeclaration.h"
     113                 : #include "nsCSSParser.h"
     114                 : #include "nsIListBoxObject.h"
     115                 : #include "nsContentUtils.h"
     116                 : #include "nsContentList.h"
     117                 : #include "nsMutationEvent.h"
     118                 : #include "nsAsyncDOMEvent.h"
     119                 : #include "nsIDOMMutationEvent.h"
     120                 : #include "nsPIDOMWindow.h"
     121                 : #include "nsDOMAttributeMap.h"
     122                 : #include "nsGkAtoms.h"
     123                 : #include "nsXULContentUtils.h"
     124                 : #include "nsNodeUtils.h"
     125                 : #include "nsFrameLoader.h"
     126                 : #include "prlog.h"
     127                 : #include "rdf.h"
     128                 : #include "nsIControllers.h"
     129                 : #include "nsAttrValueOrString.h"
     130                 : 
     131                 : // The XUL doc interface
     132                 : #include "nsIDOMXULDocument.h"
     133                 : 
     134                 : #include "nsReadableUtils.h"
     135                 : #include "nsIFrame.h"
     136                 : #include "nsNodeInfoManager.h"
     137                 : #include "nsXBLBinding.h"
     138                 : #include "nsEventDispatcher.h"
     139                 : #include "mozAutoDocUpdate.h"
     140                 : #include "nsIDOMXULCommandEvent.h"
     141                 : #include "nsIDOMNSEvent.h"
     142                 : #include "nsCCUncollectableMarker.h"
     143                 : 
     144                 : namespace css = mozilla::css;
     145                 : 
     146                 : // Global object maintenance
     147                 : nsIXBLService * nsXULElement::gXBLService = nsnull;
     148                 : 
     149                 : /**
     150                 :  * A tearoff class for nsXULElement to implement nsIScriptEventHandlerOwner.
     151                 :  */
     152                 : class nsScriptEventHandlerOwnerTearoff : public nsIScriptEventHandlerOwner
     153               0 : {
     154                 : public:
     155               0 :     nsScriptEventHandlerOwnerTearoff(nsXULElement* aElement)
     156               0 :     : mElement(aElement) {}
     157                 : 
     158               0 :     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     159            1464 :     NS_DECL_CYCLE_COLLECTION_CLASS(nsScriptEventHandlerOwnerTearoff)
     160                 : 
     161                 :     // nsIScriptEventHandlerOwner
     162                 :     virtual nsresult CompileEventHandler(nsIScriptContext* aContext,
     163                 :                                          nsIAtom *aName,
     164                 :                                          const nsAString& aBody,
     165                 :                                          const char* aURL,
     166                 :                                          PRUint32 aLineNo,
     167                 :                                          nsScriptObjectHolder<JSObject>& aHandler);
     168                 :     virtual nsresult GetCompiledEventHandler(nsIAtom *aName,
     169                 :                                              nsScriptObjectHolder<JSObject>& aHandler);
     170                 : 
     171                 : private:
     172                 :     nsRefPtr<nsXULElement> mElement;
     173                 : };
     174                 : 
     175                 : //----------------------------------------------------------------------
     176                 : 
     177                 : static NS_DEFINE_CID(kXULPopupListenerCID,        NS_XULPOPUPLISTENER_CID);
     178                 : 
     179                 : //----------------------------------------------------------------------
     180                 : 
     181                 : #ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
     182                 : PRUint32             nsXULPrototypeAttribute::gNumElements;
     183                 : PRUint32             nsXULPrototypeAttribute::gNumAttributes;
     184                 : PRUint32             nsXULPrototypeAttribute::gNumEventHandlers;
     185                 : PRUint32             nsXULPrototypeAttribute::gNumCacheTests;
     186                 : PRUint32             nsXULPrototypeAttribute::gNumCacheHits;
     187                 : PRUint32             nsXULPrototypeAttribute::gNumCacheSets;
     188                 : PRUint32             nsXULPrototypeAttribute::gNumCacheFills;
     189                 : #endif
     190                 : 
     191                 : class nsXULElementTearoff : public nsIDOMElementCSSInlineStyle,
     192                 :                             public nsIFrameLoaderOwner
     193               0 : {
     194                 : public:
     195               0 :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     196            1464 :   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULElementTearoff,
     197                 :                                            nsIDOMElementCSSInlineStyle)
     198                 : 
     199               0 :   nsXULElementTearoff(nsXULElement *aElement)
     200               0 :     : mElement(aElement)
     201                 :   {
     202               0 :   }
     203                 : 
     204               0 :   NS_IMETHOD GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
     205                 :   {
     206                 :     nsresult rv;
     207               0 :     *aStyle = static_cast<nsXULElement*>(mElement.get())->GetStyle(&rv);
     208               0 :     NS_ENSURE_SUCCESS(rv, rv);
     209               0 :     NS_ADDREF(*aStyle);
     210               0 :     return NS_OK;
     211                 :   }
     212               0 :   NS_FORWARD_NSIFRAMELOADEROWNER(static_cast<nsXULElement*>(mElement.get())->);
     213                 : private:
     214                 :   nsCOMPtr<nsIDOMXULElement> mElement;
     215                 : };
     216                 : 
     217            1464 : NS_IMPL_CYCLE_COLLECTION_1(nsXULElementTearoff, mElement)
     218                 : 
     219               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULElementTearoff)
     220               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULElementTearoff)
     221                 : 
     222               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULElementTearoff)
     223               0 :   NS_INTERFACE_MAP_ENTRY(nsIFrameLoaderOwner)
     224               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMElementCSSInlineStyle)
     225               0 : NS_INTERFACE_MAP_END_AGGREGATED(mElement)
     226                 : 
     227                 : //----------------------------------------------------------------------
     228                 : // nsXULElement
     229                 : //
     230                 : 
     231             144 : nsXULElement::nsXULElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     232                 :     : nsStyledElement(aNodeInfo),
     233             144 :       mBindingParent(nsnull)
     234                 : {
     235                 :     XUL_PROTOTYPE_ATTRIBUTE_METER(gNumElements);
     236                 : 
     237                 :     // We may be READWRITE by default; check.
     238             144 :     if (IsReadWriteTextElement()) {
     239               0 :         AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
     240               0 :         RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
     241                 :     }
     242             144 : }
     243                 : 
     244               9 : nsXULElement::nsXULSlots::nsXULSlots()
     245               9 :     : nsXULElement::nsDOMSlots()
     246                 : {
     247               9 : }
     248                 : 
     249              27 : nsXULElement::nsXULSlots::~nsXULSlots()
     250                 : {
     251               9 :     NS_IF_RELEASE(mControllers); // Forces release
     252               9 :     if (mFrameLoader) {
     253               0 :         mFrameLoader->Destroy();
     254                 :     }
     255              36 : }
     256                 : 
     257                 : void
     258               9 : nsXULElement::nsXULSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
     259                 : {
     260               9 :     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mFrameLoader");
     261               9 :     cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIFrameLoader*, mFrameLoader));
     262               9 : }
     263                 : 
     264                 : nsINode::nsSlots*
     265               9 : nsXULElement::CreateSlots()
     266                 : {
     267               9 :     return new nsXULSlots();
     268                 : }
     269                 : 
     270                 : /* static */
     271                 : already_AddRefed<nsXULElement>
     272               0 : nsXULElement::Create(nsXULPrototypeElement* aPrototype, nsINodeInfo *aNodeInfo,
     273                 :                      bool aIsScriptable)
     274                 : {
     275               0 :     nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
     276               0 :     nsXULElement *element = new nsXULElement(ni.forget());
     277               0 :     if (element) {
     278               0 :         NS_ADDREF(element);
     279                 : 
     280               0 :         element->mPrototype = aPrototype;
     281               0 :         if (aPrototype->mHasIdAttribute) {
     282               0 :             element->SetHasID();
     283                 :         }
     284               0 :         if (aPrototype->mHasClassAttribute) {
     285               0 :             element->SetFlags(NODE_MAY_HAVE_CLASS);
     286                 :         }
     287               0 :         if (aPrototype->mHasStyleAttribute) {
     288               0 :             element->SetMayHaveStyle();
     289                 :         }
     290                 : 
     291               0 :         NS_ASSERTION(aPrototype->mScriptTypeID != nsIProgrammingLanguage::UNKNOWN,
     292                 :                     "Need to know the language!");
     293               0 :         element->SetScriptTypeID(aPrototype->mScriptTypeID);
     294                 : 
     295               0 :         if (aIsScriptable) {
     296                 :             // Check each attribute on the prototype to see if we need to do
     297                 :             // any additional processing and hookup that would otherwise be
     298                 :             // done 'automagically' by SetAttr().
     299               0 :             for (PRUint32 i = 0; i < aPrototype->mNumAttributes; ++i) {
     300               0 :                 element->AddListenerFor(aPrototype->mAttributes[i].mName,
     301               0 :                                         true);
     302                 :             }
     303                 :         }
     304                 :     }
     305                 : 
     306               0 :     return element;
     307                 : }
     308                 : 
     309                 : nsresult
     310               0 : nsXULElement::Create(nsXULPrototypeElement* aPrototype,
     311                 :                      nsIDocument* aDocument,
     312                 :                      bool aIsScriptable,
     313                 :                      Element** aResult)
     314                 : {
     315                 :     // Create an nsXULElement from a prototype
     316               0 :     NS_PRECONDITION(aPrototype != nsnull, "null ptr");
     317               0 :     if (! aPrototype)
     318               0 :         return NS_ERROR_NULL_POINTER;
     319                 : 
     320               0 :     NS_PRECONDITION(aResult != nsnull, "null ptr");
     321               0 :     if (! aResult)
     322               0 :         return NS_ERROR_NULL_POINTER;
     323                 : 
     324               0 :     nsCOMPtr<nsINodeInfo> nodeInfo;
     325               0 :     if (aDocument) {
     326               0 :         nsINodeInfo* ni = aPrototype->mNodeInfo;
     327                 :         nodeInfo = aDocument->NodeInfoManager()->
     328                 :           GetNodeInfo(ni->NameAtom(), ni->GetPrefixAtom(), ni->NamespaceID(),
     329               0 :                       nsIDOMNode::ELEMENT_NODE);
     330               0 :         NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
     331                 :     }
     332                 :     else {
     333               0 :         nodeInfo = aPrototype->mNodeInfo;
     334                 :     }
     335                 : 
     336                 :     nsRefPtr<nsXULElement> element = Create(aPrototype, nodeInfo,
     337               0 :                                             aIsScriptable);
     338               0 :     if (!element) {
     339               0 :         return NS_ERROR_OUT_OF_MEMORY;
     340                 :     }
     341                 : 
     342               0 :     NS_ADDREF(*aResult = element.get());
     343                 : 
     344               0 :     return NS_OK;
     345                 : }
     346                 : 
     347                 : nsresult
     348             144 : NS_NewXULElement(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo)
     349                 : {
     350             144 :     NS_PRECONDITION(aNodeInfo.get(), "need nodeinfo for non-proto Create");
     351                 : 
     352             144 :     nsIDocument* doc = aNodeInfo.get()->GetDocument();
     353             144 :     if (doc && !doc->AllowXULXBL()) {
     354               0 :         nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
     355               0 :         return NS_ERROR_NOT_AVAILABLE;
     356                 :     }
     357                 : 
     358             144 :     NS_ADDREF(*aResult = new nsXULElement(aNodeInfo));
     359                 : 
     360             144 :     return NS_OK;
     361                 : }
     362                 : 
     363                 : void
     364               0 : NS_TrustedNewXULElement(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo)
     365                 : {
     366               0 :     NS_PRECONDITION(aNodeInfo.get(), "need nodeinfo for non-proto Create");
     367                 : 
     368                 :     // Create an nsXULElement with the specified namespace and tag.
     369               0 :     NS_ADDREF(*aResult = new nsXULElement(aNodeInfo));
     370               0 : }
     371                 : 
     372                 : //----------------------------------------------------------------------
     373                 : // nsISupports interface
     374                 : 
     375            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULElement)
     376             144 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULElement,
     377                 :                                                   nsStyledElement)
     378             144 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrototype)
     379                 :     {
     380             144 :         nsXULSlots* slots = static_cast<nsXULSlots*>(tmp->GetExistingSlots());
     381             144 :         if (slots) {
     382               9 :             slots->Traverse(cb);
     383                 :         }
     384                 :     }
     385             144 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     386                 : 
     387            3310 : NS_IMPL_ADDREF_INHERITED(nsXULElement, nsStyledElement)
     388            3310 : NS_IMPL_RELEASE_INHERITED(nsXULElement, nsStyledElement)
     389                 : 
     390              10 : DOMCI_NODE_DATA(XULElement, nsXULElement)
     391                 : 
     392            5865 : NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXULElement)
     393                 :     NS_NODE_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsXULElement)
     394                 :         NS_INTERFACE_TABLE_ENTRY(nsXULElement, nsIDOMNode)
     395                 :         NS_INTERFACE_TABLE_ENTRY(nsXULElement, nsIDOMElement)
     396                 :         NS_INTERFACE_TABLE_ENTRY(nsXULElement, nsIDOMXULElement)
     397            3309 :     NS_OFFSET_AND_INTERFACE_TABLE_END
     398            3297 :     NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE
     399               2 :     NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIScriptEventHandlerOwner,
     400                 :                                    new nsScriptEventHandlerOwnerTearoff(this))
     401               2 :     NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMElementCSSInlineStyle,
     402                 :                                    new nsXULElementTearoff(this))
     403               2 :     NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIFrameLoaderOwner,
     404                 :                                    new nsXULElementTearoff(this))
     405               2 :     NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XULElement)
     406               0 : NS_ELEMENT_INTERFACE_MAP_END
     407                 : 
     408                 : //----------------------------------------------------------------------
     409                 : // nsIDOMNode interface
     410                 : 
     411                 : nsresult
     412               0 : nsXULElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
     413                 : {
     414               0 :     *aResult = nsnull;
     415                 : 
     416                 :     // If we have a prototype, so will our clone.
     417               0 :     nsRefPtr<nsXULElement> element;
     418               0 :     if (mPrototype) {
     419               0 :         element = nsXULElement::Create(mPrototype, aNodeInfo, true);
     420               0 :         NS_ASSERTION(GetScriptTypeID() == mPrototype->mScriptTypeID,
     421                 :                      "Didn't get the default language from proto?");
     422                 :     }
     423                 :     else {
     424               0 :         nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
     425               0 :         element = new nsXULElement(ni.forget());
     426               0 :         if (element) {
     427                 :                 // If created from a prototype, we will already have the script
     428                 :                 // language specified by the proto - otherwise copy it directly
     429               0 :                 element->SetScriptTypeID(GetScriptTypeID());
     430                 :         }
     431                 :     }
     432                 : 
     433               0 :     if (!element) {
     434               0 :         return NS_ERROR_OUT_OF_MEMORY;
     435                 :     }
     436                 : 
     437                 :     // XXX TODO: set up RDF generic builder n' stuff if there is a
     438                 :     // 'datasources' attribute? This is really kind of tricky,
     439                 :     // because then we'd need to -selectively- copy children that
     440                 :     // -weren't- generated from RDF. Ugh. Forget it.
     441                 : 
     442                 :     // Note that we're _not_ copying mControllers.
     443                 : 
     444               0 :     nsresult rv = CopyInnerTo(element);
     445               0 :     if (NS_SUCCEEDED(rv)) {
     446               0 :         NS_ADDREF(*aResult = element);
     447                 :     }
     448                 : 
     449               0 :     return rv;
     450                 : }
     451                 : 
     452                 : //----------------------------------------------------------------------
     453                 : 
     454                 : NS_IMETHODIMP
     455              45 : nsXULElement::GetElementsByAttribute(const nsAString& aAttribute,
     456                 :                                      const nsAString& aValue,
     457                 :                                      nsIDOMNodeList** aReturn)
     458                 : {
     459              90 :     nsCOMPtr<nsIAtom> attrAtom(do_GetAtom(aAttribute));
     460              45 :     NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY);
     461              45 :     void* attrValue = new nsString(aValue);
     462              45 :     NS_ENSURE_TRUE(attrValue, NS_ERROR_OUT_OF_MEMORY);
     463                 :     nsContentList *list = 
     464                 :         new nsContentList(this,
     465                 :                           nsXULDocument::MatchAttribute,
     466                 :                           nsContentUtils::DestroyMatchString,
     467                 :                           attrValue,
     468                 :                           true,
     469                 :                           attrAtom,
     470              90 :                           kNameSpaceID_Unknown);
     471              45 :     NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
     472                 : 
     473              45 :     NS_ADDREF(*aReturn = list);
     474              45 :     return NS_OK;
     475                 : }
     476                 : 
     477                 : NS_IMETHODIMP
     478              37 : nsXULElement::GetElementsByAttributeNS(const nsAString& aNamespaceURI,
     479                 :                                        const nsAString& aAttribute,
     480                 :                                        const nsAString& aValue,
     481                 :                                        nsIDOMNodeList** aReturn)
     482                 : {
     483              74 :     nsCOMPtr<nsIAtom> attrAtom(do_GetAtom(aAttribute));
     484              37 :     NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY);
     485                 : 
     486              37 :     PRInt32 nameSpaceId = kNameSpaceID_Wildcard;
     487              37 :     if (!aNamespaceURI.EqualsLiteral("*")) {
     488                 :       nsresult rv =
     489              20 :         nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
     490              20 :                                                               nameSpaceId);
     491              20 :       NS_ENSURE_SUCCESS(rv, rv);
     492                 :     }
     493                 : 
     494              37 :     void* attrValue = new nsString(aValue);
     495              37 :     NS_ENSURE_TRUE(attrValue, NS_ERROR_OUT_OF_MEMORY);
     496                 :     
     497                 :     nsContentList *list = 
     498                 :         new nsContentList(this,
     499                 :                           nsXULDocument::MatchAttribute,
     500                 :                           nsContentUtils::DestroyMatchString,
     501                 :                           attrValue,
     502                 :                           true,
     503                 :                           attrAtom,
     504              74 :                           nameSpaceId);
     505              37 :     NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
     506                 : 
     507              37 :     NS_ADDREF(*aReturn = list);
     508              37 :     return NS_OK;
     509                 : }
     510                 : 
     511                 : nsEventListenerManager*
     512               0 : nsXULElement::GetEventListenerManagerForAttr(nsIAtom* aAttrName, bool* aDefer)
     513                 : {
     514                 :     // XXXbz sXBL/XBL2 issue: should we instead use GetCurrentDoc()
     515                 :     // here, override BindToTree for those classes and munge event
     516                 :     // listeners there?
     517               0 :     nsIDocument* doc = OwnerDoc();
     518                 : 
     519                 :     nsPIDOMWindow *window;
     520               0 :     Element *root = doc->GetRootElement();
     521               0 :     if ((!root || root == this) && !mNodeInfo->Equals(nsGkAtoms::overlay) &&
     522               0 :         (window = doc->GetInnerWindow()) && window->IsInnerWindow()) {
     523                 : 
     524               0 :         nsCOMPtr<nsIDOMEventTarget> piTarget = do_QueryInterface(window);
     525                 : 
     526               0 :         *aDefer = false;
     527               0 :         return piTarget->GetListenerManager(true);
     528                 :     }
     529                 : 
     530               0 :     return nsStyledElement::GetEventListenerManagerForAttr(aAttrName, aDefer);
     531                 : }
     532                 : 
     533                 : // returns true if the element is not a list
     534               0 : static bool IsNonList(nsINodeInfo* aNodeInfo)
     535                 : {
     536               0 :   return !aNodeInfo->Equals(nsGkAtoms::tree) &&
     537               0 :          !aNodeInfo->Equals(nsGkAtoms::listbox) &&
     538               0 :          !aNodeInfo->Equals(nsGkAtoms::richlistbox);
     539                 : }
     540                 : 
     541                 : bool
     542               0 : nsXULElement::IsFocusable(PRInt32 *aTabIndex, bool aWithMouse)
     543                 : {
     544                 :   /* 
     545                 :    * Returns true if an element may be focused, and false otherwise. The inout
     546                 :    * argument aTabIndex will be set to the tab order index to be used; -1 for
     547                 :    * elements that should not be part of the tab order and a greater value to
     548                 :    * indicate its tab order.
     549                 :    *
     550                 :    * Confusingly, the supplied value for the aTabIndex argument may indicate
     551                 :    * whether the element may be focused as a result of the -moz-user-focus
     552                 :    * property, where -1 means no and 0 means yes.
     553                 :    *
     554                 :    * For controls, the element cannot be focused and is not part of the tab
     555                 :    * order if it is disabled.
     556                 :    *
     557                 :    * Controls (those that implement nsIDOMXULControlElement):
     558                 :    *  *aTabIndex = -1  no tabindex     Not focusable or tabbable
     559                 :    *  *aTabIndex = -1  tabindex="-1"   Not focusable or tabbable
     560                 :    *  *aTabIndex = -1  tabindex=">=0"  Focusable and tabbable
     561                 :    *  *aTabIndex >= 0  no tabindex     Focusable and tabbable
     562                 :    *  *aTabIndex >= 0  tabindex="-1"   Focusable but not tabbable
     563                 :    *  *aTabIndex >= 0  tabindex=">=0"  Focusable and tabbable
     564                 :    * Non-controls:
     565                 :    *  *aTabIndex = -1                  Not focusable or tabbable
     566                 :    *  *aTabIndex >= 0                  Focusable and tabbable
     567                 :    *
     568                 :    * If aTabIndex is null, then the tabindex is not computed, and
     569                 :    * true is returned for non-disabled controls and false otherwise.
     570                 :    */
     571                 : 
     572                 :   // elements are not focusable by default
     573               0 :   bool shouldFocus = false;
     574                 : 
     575                 : #ifdef XP_MACOSX
     576                 :   // on Mac, mouse interactions only focus the element if it's a list
     577                 :   if (aWithMouse && IsNonList(mNodeInfo))
     578                 :     return false;
     579                 : #endif
     580                 : 
     581               0 :   nsCOMPtr<nsIDOMXULControlElement> xulControl = do_QueryObject(this);
     582               0 :   if (xulControl) {
     583                 :     // a disabled element cannot be focused and is not part of the tab order
     584                 :     bool disabled;
     585               0 :     xulControl->GetDisabled(&disabled);
     586               0 :     if (disabled) {
     587               0 :       if (aTabIndex)
     588               0 :         *aTabIndex = -1;
     589               0 :       return false;
     590                 :     }
     591               0 :     shouldFocus = true;
     592                 :   }
     593                 : 
     594               0 :   if (aTabIndex) {
     595               0 :     if (xulControl) {
     596               0 :       if (HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
     597                 :         // if either the aTabIndex argument or a specified tabindex is non-negative,
     598                 :         // the element becomes focusable.
     599               0 :         PRInt32 tabIndex = 0;
     600               0 :         xulControl->GetTabIndex(&tabIndex);
     601               0 :         shouldFocus = *aTabIndex >= 0 || tabIndex >= 0;
     602               0 :         *aTabIndex = tabIndex;
     603                 :       }
     604                 :       else {
     605                 :         // otherwise, if there is no tabindex attribute, just use the value of
     606                 :         // *aTabIndex to indicate focusability. Reset any supplied tabindex to 0.
     607               0 :         shouldFocus = *aTabIndex >= 0;
     608               0 :         if (shouldFocus)
     609               0 :           *aTabIndex = 0;
     610                 :       }
     611                 : 
     612               0 :       if (shouldFocus && sTabFocusModelAppliesToXUL &&
     613               0 :           !(sTabFocusModel & eTabFocus_formElementsMask)) {
     614                 :         // By default, the tab focus model doesn't apply to xul element on any system but OS X.
     615                 :         // on OS X we're following it for UI elements (XUL) as sTabFocusModel is based on
     616                 :         // "Full Keyboard Access" system setting (see mac/nsILookAndFeel).
     617                 :         // both textboxes and list elements (i.e. trees and list) should always be focusable
     618                 :         // (textboxes are handled as html:input)
     619                 :         // For compatibility, we only do this for controls, otherwise elements like <browser>
     620                 :         // cannot take this focus.
     621               0 :         if (IsNonList(mNodeInfo))
     622               0 :           *aTabIndex = -1;
     623                 :       }
     624                 :     }
     625                 :     else {
     626               0 :       shouldFocus = *aTabIndex >= 0;
     627                 :     }
     628                 :   }
     629                 : 
     630               0 :   return shouldFocus;
     631                 : }
     632                 : 
     633                 : void
     634               0 : nsXULElement::PerformAccesskey(bool aKeyCausesActivation,
     635                 :                                bool aIsTrustedEvent)
     636                 : {
     637               0 :     nsCOMPtr<nsIContent> content(this);
     638                 : 
     639               0 :     if (Tag() == nsGkAtoms::label) {
     640               0 :         nsCOMPtr<nsIDOMElement> element;
     641                 : 
     642               0 :         nsAutoString control;
     643               0 :         GetAttr(kNameSpaceID_None, nsGkAtoms::control, control);
     644               0 :         if (!control.IsEmpty()) {
     645                 :             nsCOMPtr<nsIDOMDocument> domDocument =
     646               0 :                 do_QueryInterface(content->GetCurrentDoc());
     647               0 :             if (domDocument)
     648               0 :                 domDocument->GetElementById(control, getter_AddRefs(element));
     649                 :         }
     650                 :         // here we'll either change |content| to the element referenced by
     651                 :         // |element|, or clear it.
     652               0 :         content = do_QueryInterface(element);
     653                 : 
     654               0 :         if (!content)
     655                 :             return;
     656                 :     }
     657                 : 
     658               0 :     nsIFrame* frame = content->GetPrimaryFrame();
     659               0 :     if (!frame || !frame->IsVisibleConsideringAncestors())
     660                 :         return;
     661                 : 
     662               0 :     nsXULElement* elm = FromContent(content);
     663               0 :     if (elm) {
     664                 :         // Define behavior for each type of XUL element.
     665               0 :         nsIAtom *tag = content->Tag();
     666               0 :         if (tag != nsGkAtoms::toolbarbutton) {
     667               0 :           nsIFocusManager* fm = nsFocusManager::GetFocusManager();
     668               0 :           if (fm) {
     669               0 :             nsCOMPtr<nsIDOMElement> element;
     670                 :             // for radio buttons, focus the radiogroup instead
     671               0 :             if (tag == nsGkAtoms::radio) {
     672               0 :               nsCOMPtr<nsIDOMXULSelectControlItemElement> controlItem(do_QueryInterface(content));
     673               0 :               if (controlItem) {
     674                 :                 bool disabled;
     675               0 :                 controlItem->GetDisabled(&disabled);
     676               0 :                 if (!disabled) {
     677               0 :                   nsCOMPtr<nsIDOMXULSelectControlElement> selectControl;
     678               0 :                   controlItem->GetControl(getter_AddRefs(selectControl));
     679               0 :                   element = do_QueryInterface(selectControl);
     680                 :                 }
     681                 :               }
     682                 :             }
     683                 :             else {
     684               0 :               element = do_QueryInterface(content);
     685                 :             }
     686               0 :             if (element)
     687               0 :               fm->SetFocus(element, nsIFocusManager::FLAG_BYKEY);
     688                 :           }
     689                 :         }
     690               0 :         if (aKeyCausesActivation && tag != nsGkAtoms::textbox && tag != nsGkAtoms::menulist) {
     691               0 :           elm->ClickWithInputSource(nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD);
     692                 :         }
     693                 :     }
     694                 :     else {
     695               0 :         content->PerformAccesskey(aKeyCausesActivation, aIsTrustedEvent);
     696                 :     }
     697                 : }
     698                 : 
     699                 : 
     700                 : //----------------------------------------------------------------------
     701                 : // nsIScriptEventHandlerOwner interface
     702                 : 
     703            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsScriptEventHandlerOwnerTearoff)
     704               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsScriptEventHandlerOwnerTearoff)
     705               0 :   tmp->mElement = nsnull;
     706               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     707               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsScriptEventHandlerOwnerTearoff)
     708               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mElement");
     709               0 :   cb.NoteXPCOMChild(static_cast<nsIContent*>(tmp->mElement));
     710               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     711                 : 
     712               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsScriptEventHandlerOwnerTearoff)
     713               0 :   NS_INTERFACE_MAP_ENTRY(nsIScriptEventHandlerOwner)
     714               0 : NS_INTERFACE_MAP_END_AGGREGATED(mElement)
     715                 : 
     716               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsScriptEventHandlerOwnerTearoff)
     717               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsScriptEventHandlerOwnerTearoff)
     718                 : 
     719                 : nsresult
     720               0 : nsScriptEventHandlerOwnerTearoff::GetCompiledEventHandler(
     721                 :                                                 nsIAtom *aName,
     722                 :                                                 nsScriptObjectHolder<JSObject>& aHandler)
     723                 : {
     724                 :     XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheTests);
     725               0 :     aHandler.drop();
     726                 : 
     727                 :     nsXULPrototypeAttribute *attr =
     728               0 :         mElement->FindPrototypeAttribute(kNameSpaceID_None, aName);
     729               0 :     if (attr) {
     730                 :         XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheHits);
     731               0 :         aHandler.set(attr->mEventHandler);
     732                 :     }
     733                 : 
     734               0 :     return NS_OK;
     735                 : }
     736                 : 
     737                 : nsresult
     738               0 : nsScriptEventHandlerOwnerTearoff::CompileEventHandler(
     739                 :                                                 nsIScriptContext* aContext,
     740                 :                                                 nsIAtom *aName,
     741                 :                                                 const nsAString& aBody,
     742                 :                                                 const char* aURL,
     743                 :                                                 PRUint32 aLineNo,
     744                 :                                                 nsScriptObjectHolder<JSObject>& aHandler)
     745                 : {
     746                 :     nsresult rv;
     747                 : 
     748                 :     XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheSets);
     749                 : 
     750                 :     // XXX sXBL/XBL2 issue! Owner or current document?
     751               0 :     nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mElement->OwnerDoc());
     752                 : 
     753               0 :     nsIScriptContext* context = NULL;
     754               0 :     nsXULPrototypeElement* elem = mElement->mPrototype;
     755               0 :     if (elem && xuldoc) {
     756                 :         // It'll be shared among the instances of the prototype.
     757                 : 
     758                 :         // Use the prototype document's special context.  Because
     759                 :         // scopeObject is null, the JS engine has no other source of
     760                 :         // <the-new-shared-event-handler>.__proto__ than to look in
     761                 :         // cx->globalObject for Function.prototype.  That prototype
     762                 :         // keeps the global object alive, so if we use this document's
     763                 :         // global object, we'll be putting something in the prototype
     764                 :         // that protects this document's global object from GC.
     765               0 :         nsCOMPtr<nsIScriptGlobalObjectOwner> globalOwner;
     766               0 :         rv = xuldoc->GetScriptGlobalObjectOwner(getter_AddRefs(globalOwner));
     767               0 :         NS_ENSURE_SUCCESS(rv, rv);
     768               0 :         NS_ENSURE_TRUE(globalOwner, NS_ERROR_UNEXPECTED);
     769                 : 
     770               0 :         nsIScriptGlobalObject* global = globalOwner->GetScriptGlobalObject();
     771               0 :         NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
     772                 : 
     773               0 :         context = global->GetScriptContext(aContext->GetScriptTypeID());
     774                 :         // It could be possible the language has been setup on aContext but
     775                 :         // not on the global - we don't demand-create language contexts on the
     776                 :         // nsGlobalWindow
     777               0 :         NS_ASSERTION(context,
     778                 :                      "Failed to get a language context from the global!?");
     779               0 :         NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED);
     780                 :     }
     781                 :     else {
     782               0 :         context = aContext;
     783                 :     }
     784                 : 
     785                 :     // Compile the event handler
     786                 :     PRUint32 argCount;
     787                 :     const char **argNames;
     788                 :     nsContentUtils::GetEventArgNames(kNameSpaceID_XUL, aName, &argCount,
     789               0 :                                      &argNames);
     790                 : 
     791               0 :     nsCxPusher pusher;
     792               0 :     if (!pusher.Push(context->GetNativeContext())) {
     793               0 :       return NS_ERROR_FAILURE;
     794                 :     }
     795                 : 
     796                 :     rv = context->CompileEventHandler(aName, argCount, argNames,
     797                 :                                       aBody, aURL, aLineNo,
     798                 :                                       SCRIPTVERSION_DEFAULT,  // for now?
     799               0 :                                       aHandler);
     800               0 :     if (NS_FAILED(rv)) return rv;
     801                 : 
     802                 :     nsXULPrototypeAttribute *attr =
     803               0 :         mElement->FindPrototypeAttribute(kNameSpaceID_None, aName);
     804               0 :     if (attr) {
     805                 :         XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills);
     806                 :         // take a copy of the event handler, and tell the language about it.
     807               0 :         if (aHandler) {
     808               0 :             NS_ASSERTION(!attr->mEventHandler, "Leaking handler.");
     809                 : 
     810               0 :             rv = nsContentUtils::HoldScriptObject(aContext->GetScriptTypeID(),
     811                 :                                                   elem,
     812                 :                                                   &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode),
     813               0 :                                                   aHandler.get(),
     814               0 :                                                   elem->mHoldsScriptObject);
     815               0 :             if (NS_FAILED(rv)) return rv;
     816                 : 
     817               0 :             elem->mHoldsScriptObject = true;
     818                 :         }
     819               0 :         attr->mEventHandler = aHandler.get();
     820                 :     }
     821                 : 
     822               0 :     return NS_OK;
     823                 : }
     824                 : 
     825                 : void
     826               0 : nsXULElement::AddListenerFor(const nsAttrName& aName,
     827                 :                              bool aCompileEventHandlers)
     828                 : {
     829                 :     // If appropriate, add a popup listener and/or compile the event
     830                 :     // handler. Called when we change the element's document, create a
     831                 :     // new element, change an attribute's value, etc.
     832                 :     // Eventlistenener-attributes are always in the null namespace
     833               0 :     if (aName.IsAtom()) {
     834               0 :         nsIAtom *attr = aName.Atom();
     835               0 :         MaybeAddPopupListener(attr);
     836               0 :         if (aCompileEventHandlers &&
     837               0 :             nsContentUtils::IsEventAttributeName(attr, EventNameType_XUL)) {
     838               0 :             nsAutoString value;
     839               0 :             GetAttr(kNameSpaceID_None, attr, value);
     840               0 :             AddScriptEventListener(attr, value, true);
     841                 :         }
     842                 :     }
     843               0 : }
     844                 : 
     845                 : void
     846              66 : nsXULElement::MaybeAddPopupListener(nsIAtom* aLocalName)
     847                 : {
     848                 :     // If appropriate, add a popup listener. Called when we change the
     849                 :     // element's document, create a new element, change an attribute's
     850                 :     // value, etc.
     851              66 :     if (aLocalName == nsGkAtoms::menu ||
     852                 :         aLocalName == nsGkAtoms::contextmenu ||
     853                 :         // XXXdwh popup and context are deprecated
     854                 :         aLocalName == nsGkAtoms::popup ||
     855                 :         aLocalName == nsGkAtoms::context) {
     856               0 :         AddPopupListener(aLocalName);
     857                 :     }
     858              66 : }
     859                 : 
     860                 : //----------------------------------------------------------------------
     861                 : //
     862                 : // nsIContent interface
     863                 : //
     864                 : void
     865             144 : nsXULElement::UpdateEditableState(bool aNotify)
     866                 : {
     867                 :     // Don't call through to nsGenericElement here because the things
     868                 :     // it does don't work for cases when we're an editable control.
     869             144 :     nsIContent *parent = GetParent();
     870                 : 
     871             144 :     SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
     872             144 :     UpdateState(aNotify);
     873             144 : }
     874                 : 
     875                 : nsresult
     876             144 : nsXULElement::BindToTree(nsIDocument* aDocument,
     877                 :                          nsIContent* aParent,
     878                 :                          nsIContent* aBindingParent,
     879                 :                          bool aCompileEventHandlers)
     880                 : {
     881                 :   nsresult rv = nsStyledElement::BindToTree(aDocument, aParent,
     882                 :                                             aBindingParent,
     883             144 :                                             aCompileEventHandlers);
     884             144 :   NS_ENSURE_SUCCESS(rv, rv);
     885                 : 
     886             144 :   if (aDocument) {
     887             144 :       NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
     888                 :                    "Missing a script blocker!");
     889                 :       // We're in a document now.  Kick off the frame load.
     890             144 :       LoadSrc();
     891                 :   }
     892                 : 
     893             144 :   return rv;
     894                 : }
     895                 : 
     896                 : void
     897             435 : nsXULElement::UnbindFromTree(bool aDeep, bool aNullParent)
     898                 : {
     899                 :     // mControllers can own objects that are implemented
     900                 :     // in JavaScript (such as some implementations of
     901                 :     // nsIControllers.  These objects prevent their global
     902                 :     // object's script object from being garbage collected,
     903                 :     // which means JS continues to hold an owning reference
     904                 :     // to the nsGlobalWindow, which owns the document,
     905                 :     // which owns this content.  That's a cycle, so we break
     906                 :     // it here.  (It might be better to break this by releasing
     907                 :     // mDocument in nsGlobalWindow::SetDocShell, but I'm not
     908                 :     // sure whether that would fix all possible cycles through
     909                 :     // mControllers.)
     910             435 :     nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingDOMSlots());
     911             435 :     if (slots) {
     912              23 :         NS_IF_RELEASE(slots->mControllers);
     913              23 :         if (slots->mFrameLoader) {
     914                 :             // This element is being taken out of the document, destroy the
     915                 :             // possible frame loader.
     916                 :             // XXXbz we really want to only partially destroy the frame
     917                 :             // loader... we don't want to tear down the docshell.  Food for
     918                 :             // later bug.
     919               0 :             slots->mFrameLoader->Destroy();
     920               0 :             slots->mFrameLoader = nsnull;
     921                 :         }
     922                 :     }
     923                 : 
     924             435 :     nsStyledElement::UnbindFromTree(aDeep, aNullParent);
     925             435 : }
     926                 : 
     927                 : nsresult
     928               0 : nsXULElement::RemoveChildAt(PRUint32 aIndex, bool aNotify)
     929                 : {
     930                 :     nsresult rv;
     931               0 :     nsCOMPtr<nsIContent> oldKid = mAttrsAndChildren.GetSafeChildAt(aIndex);
     932               0 :     if (!oldKid) {
     933               0 :       return NS_OK;
     934                 :     }
     935                 : 
     936                 :     // On the removal of a <treeitem>, <treechildren>, or <treecell> element,
     937                 :     // the possibility exists that some of the items in the removed subtree
     938                 :     // are selected (and therefore need to be deselected). We need to account for this.
     939               0 :     nsCOMPtr<nsIDOMXULMultiSelectControlElement> controlElement;
     940               0 :     nsCOMPtr<nsIListBoxObject> listBox;
     941               0 :     bool fireSelectionHandler = false;
     942                 : 
     943                 :     // -1 = do nothing, -2 = null out current item
     944                 :     // anything else = index to re-set as current
     945               0 :     PRInt32 newCurrentIndex = -1;
     946                 : 
     947               0 :     if (oldKid->NodeInfo()->Equals(nsGkAtoms::listitem, kNameSpaceID_XUL)) {
     948                 :       // This is the nasty case. We have (potentially) a slew of selected items
     949                 :       // and cells going away.
     950                 :       // First, retrieve the tree.
     951                 :       // Check first whether this element IS the tree
     952               0 :       controlElement = do_QueryObject(this);
     953                 : 
     954                 :       // If it's not, look at our parent
     955               0 :       if (!controlElement)
     956               0 :         rv = GetParentTree(getter_AddRefs(controlElement));
     957                 : 
     958               0 :       nsCOMPtr<nsIDOMElement> oldKidElem = do_QueryInterface(oldKid);
     959               0 :       if (controlElement && oldKidElem) {
     960                 :         // Iterate over all of the items and find out if they are contained inside
     961                 :         // the removed subtree.
     962                 :         PRInt32 length;
     963               0 :         controlElement->GetSelectedCount(&length);
     964               0 :         for (PRInt32 i = 0; i < length; i++) {
     965               0 :           nsCOMPtr<nsIDOMXULSelectControlItemElement> node;
     966               0 :           controlElement->GetSelectedItem(i, getter_AddRefs(node));
     967                 :           // we need to QI here to do an XPCOM-correct pointercompare
     968               0 :           nsCOMPtr<nsIDOMElement> selElem = do_QueryInterface(node);
     969               0 :           if (selElem == oldKidElem &&
     970               0 :               NS_SUCCEEDED(controlElement->RemoveItemFromSelection(node))) {
     971               0 :             length--;
     972               0 :             i--;
     973               0 :             fireSelectionHandler = true;
     974                 :           }
     975                 :         }
     976                 : 
     977               0 :         nsCOMPtr<nsIDOMXULSelectControlItemElement> curItem;
     978               0 :         controlElement->GetCurrentItem(getter_AddRefs(curItem));
     979               0 :         nsCOMPtr<nsIContent> curNode = do_QueryInterface(curItem);
     980               0 :         if (curNode && nsContentUtils::ContentIsDescendantOf(curNode, oldKid)) {
     981                 :             // Current item going away
     982               0 :             nsCOMPtr<nsIBoxObject> box;
     983               0 :             controlElement->GetBoxObject(getter_AddRefs(box));
     984               0 :             listBox = do_QueryInterface(box);
     985               0 :             if (listBox && oldKidElem) {
     986               0 :               listBox->GetIndexOfItem(oldKidElem, &newCurrentIndex);
     987                 :             }
     988                 : 
     989                 :             // If any of this fails, we'll just set the current item to null
     990               0 :             if (newCurrentIndex == -1)
     991               0 :               newCurrentIndex = -2;
     992                 :         }
     993                 :       }
     994                 :     }
     995                 : 
     996               0 :     rv = nsStyledElement::RemoveChildAt(aIndex, aNotify);
     997                 :     
     998               0 :     if (newCurrentIndex == -2)
     999               0 :         controlElement->SetCurrentItem(nsnull);
    1000               0 :     else if (newCurrentIndex > -1) {
    1001                 :         // Make sure the index is still valid
    1002                 :         PRInt32 treeRows;
    1003               0 :         listBox->GetRowCount(&treeRows);
    1004               0 :         if (treeRows > 0) {
    1005               0 :             newCurrentIndex = NS_MIN((treeRows - 1), newCurrentIndex);
    1006               0 :             nsCOMPtr<nsIDOMElement> newCurrentItem;
    1007               0 :             listBox->GetItemAtIndex(newCurrentIndex, getter_AddRefs(newCurrentItem));
    1008               0 :             nsCOMPtr<nsIDOMXULSelectControlItemElement> xulCurItem = do_QueryInterface(newCurrentItem);
    1009               0 :             if (xulCurItem)
    1010               0 :                 controlElement->SetCurrentItem(xulCurItem);
    1011                 :         } else {
    1012               0 :             controlElement->SetCurrentItem(nsnull);
    1013                 :         }
    1014                 :     }
    1015                 : 
    1016                 :     nsIDocument* doc;
    1017               0 :     if (fireSelectionHandler && (doc = GetCurrentDoc())) {
    1018                 :       nsContentUtils::DispatchTrustedEvent(doc,
    1019                 :                                            static_cast<nsIContent*>(this),
    1020               0 :                                            NS_LITERAL_STRING("select"),
    1021                 :                                            false,
    1022               0 :                                            true);
    1023                 :     }
    1024                 : 
    1025               0 :     return rv;
    1026                 : }
    1027                 : 
    1028                 : void
    1029               0 : nsXULElement::UnregisterAccessKey(const nsAString& aOldValue)
    1030                 : {
    1031                 :     // If someone changes the accesskey, unregister the old one
    1032                 :     //
    1033               0 :     nsIDocument* doc = GetCurrentDoc();
    1034               0 :     if (doc && !aOldValue.IsEmpty()) {
    1035               0 :         nsIPresShell *shell = doc->GetShell();
    1036                 : 
    1037               0 :         if (shell) {
    1038               0 :             nsIContent *content = this;
    1039                 : 
    1040                 :             // find out what type of content node this is
    1041               0 :             if (mNodeInfo->Equals(nsGkAtoms::label)) {
    1042                 :                 // For anonymous labels the unregistering must
    1043                 :                 // occur on the binding parent control.
    1044                 :                 // XXXldb: And what if the binding parent is null?
    1045               0 :                 content = GetBindingParent();
    1046                 :             }
    1047                 : 
    1048               0 :             if (content) {
    1049                 :                 shell->GetPresContext()->EventStateManager()->
    1050               0 :                     UnregisterAccessKey(content, aOldValue.First());
    1051                 :             }
    1052                 :         }
    1053                 :     }
    1054               0 : }
    1055                 : 
    1056                 : nsresult
    1057             184 : nsXULElement::BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
    1058                 :                             const nsAttrValueOrString* aValue, bool aNotify)
    1059                 : {
    1060             184 :     if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::accesskey &&
    1061               0 :         IsInDoc()) {
    1062               0 :         const nsAttrValue* attrVal = FindLocalOrProtoAttr(aNamespaceID, aName);
    1063               0 :         if (attrVal) {
    1064               0 :             nsAutoString oldValue;
    1065               0 :             attrVal->ToString(oldValue);
    1066               0 :             UnregisterAccessKey(oldValue);
    1067                 :         }
    1068                 :     } 
    1069             184 :     else if (aNamespaceID == kNameSpaceID_None && (aName ==
    1070               0 :              nsGkAtoms::command || aName == nsGkAtoms::observes) && IsInDoc()) {
    1071                 : //         XXX sXBL/XBL2 issue! Owner or current document?
    1072               0 :         nsAutoString oldValue;
    1073               0 :         GetAttr(kNameSpaceID_None, nsGkAtoms::observes, oldValue);
    1074               0 :         if (oldValue.IsEmpty()) {
    1075               0 :           GetAttr(kNameSpaceID_None, nsGkAtoms::command, oldValue);
    1076                 :         }
    1077                 : 
    1078               0 :         if (!oldValue.IsEmpty()) {
    1079               0 :           RemoveBroadcaster(oldValue);
    1080                 :         }
    1081                 :     }
    1082             250 :     else if (aNamespaceID == kNameSpaceID_None &&
    1083                 :              aValue &&
    1084              66 :              mNodeInfo->Equals(nsGkAtoms::window) &&
    1085                 :              aName == nsGkAtoms::chromemargin) {
    1086               0 :       nsAttrValue attrValue;
    1087                 :       // Make sure the margin format is valid first
    1088               0 :       if (!attrValue.ParseIntMarginValue(aValue->String())) {
    1089               0 :         return NS_ERROR_INVALID_ARG;
    1090                 :       }
    1091                 :     }
    1092                 : 
    1093                 :     return nsStyledElement::BeforeSetAttr(aNamespaceID, aName,
    1094             184 :                                           aValue, aNotify);
    1095                 : }
    1096                 : 
    1097                 : nsresult
    1098             184 : nsXULElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
    1099                 :                            const nsAttrValue* aValue, bool aNotify)
    1100                 : {
    1101             184 :     if (aNamespaceID == kNameSpaceID_None) {
    1102                 :         // XXX UnsetAttr handles more attributes than we do. See bug 233642.
    1103                 : 
    1104                 :         // Add popup and event listeners. We can't call AddListenerFor since
    1105                 :         // the attribute isn't set yet.
    1106              66 :         MaybeAddPopupListener(aName);
    1107              66 :         if (nsContentUtils::IsEventAttributeName(aName, EventNameType_XUL) && aValue) {
    1108                 :             // If mPrototype->mScriptTypeID != GetScriptTypeID(), it means
    1109                 :             // we are resolving an overlay with a different default script
    1110                 :             // language.  We can't defer compilation of those handlers as
    1111                 :             // we will have lost the script language (storing it on each
    1112                 :             // nsXULPrototypeAttribute is expensive!)
    1113               0 :             bool defer = mPrototype == nsnull ||
    1114               0 :                            mPrototype->mScriptTypeID == GetScriptTypeID();
    1115               0 :             if (aValue->Type() == nsAttrValue::eString) {
    1116               0 :                 AddScriptEventListener(aName, aValue->GetStringValue(), defer);
    1117                 :             } else {
    1118               0 :                 nsAutoString body;
    1119               0 :                 aValue->ToString(body);
    1120               0 :                 AddScriptEventListener(aName, body, defer);
    1121                 :             }
    1122                 :         }
    1123                 : 
    1124                 :         // Hide chrome if needed
    1125              66 :         if (mNodeInfo->Equals(nsGkAtoms::window) && aValue) {
    1126               0 :             if (aName == nsGkAtoms::hidechrome) {
    1127                 :                 HideWindowChrome(
    1128               0 :                   aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
    1129                 :             }
    1130               0 :             else if (aName == nsGkAtoms::chromemargin) {
    1131               0 :                 SetChromeMargins(aValue);
    1132                 :             }
    1133                 :         }
    1134                 : 
    1135                 :         // title, (in)activetitlebarcolor and drawintitlebar are settable on
    1136                 :         // any root node (windows, dialogs, etc)
    1137              66 :         nsIDocument *document = GetCurrentDoc();
    1138              66 :         if (document && document->GetRootElement() == this) {
    1139               0 :             if (aName == nsGkAtoms::title) {
    1140               0 :                 document->NotifyPossibleTitleChange(false);
    1141                 :             }
    1142               0 :             else if ((aName == nsGkAtoms::activetitlebarcolor ||
    1143                 :                       aName == nsGkAtoms::inactivetitlebarcolor) && aValue) {
    1144               0 :                 nscolor color = NS_RGBA(0, 0, 0, 0);
    1145               0 :                 if (aValue->Type() == nsAttrValue::eColor) {
    1146               0 :                     aValue->GetColorValue(color);
    1147                 :                 } else {
    1148               0 :                     nsAutoString tmp;
    1149               0 :                     nsAttrValue attrValue;
    1150               0 :                     aValue->ToString(tmp);
    1151               0 :                     attrValue.ParseColor(tmp);
    1152               0 :                     attrValue.GetColorValue(color);
    1153                 :                 }
    1154               0 :                 SetTitlebarColor(color, aName == nsGkAtoms::activetitlebarcolor);
    1155                 :             }
    1156               0 :             else if (aName == nsGkAtoms::drawintitlebar) {
    1157                 :                 SetDrawsInTitlebar(aValue &&
    1158               0 :                     aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
    1159                 :             }
    1160               0 :             else if (aName == nsGkAtoms::localedir) {
    1161                 :                 // if the localedir changed on the root element, reset the document direction
    1162               0 :                 nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(document);
    1163               0 :                 if (xuldoc) {
    1164               0 :                     xuldoc->ResetDocumentDirection();
    1165                 :                 }
    1166                 :             }
    1167               0 :             else if (aName == nsGkAtoms::lwtheme ||
    1168                 :                      aName == nsGkAtoms::lwthemetextcolor) {
    1169                 :                 // if the lwtheme changed, make sure to reset the document lwtheme cache
    1170               0 :                 nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(document);
    1171               0 :                 if (xuldoc) {
    1172               0 :                     xuldoc->ResetDocumentLWTheme();
    1173                 :                 }
    1174                 :             }
    1175                 :         }
    1176                 : 
    1177              66 :         if (aName == nsGkAtoms::src && document) {
    1178               0 :             LoadSrc();
    1179                 :         }
    1180                 : 
    1181                 :         // XXX need to check if they're changing an event handler: if
    1182                 :         // so, then we need to unhook the old one.  Or something.
    1183                 :     }
    1184                 : 
    1185                 :     return nsStyledElement::AfterSetAttr(aNamespaceID, aName,
    1186             184 :                                          aValue, aNotify);
    1187                 : }
    1188                 : 
    1189                 : bool
    1190             184 : nsXULElement::ParseAttribute(PRInt32 aNamespaceID,
    1191                 :                              nsIAtom* aAttribute,
    1192                 :                              const nsAString& aValue,
    1193                 :                              nsAttrValue& aResult)
    1194                 : {
    1195                 :     // Parse into a nsAttrValue
    1196             184 :     if (!nsStyledElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
    1197             184 :                                          aResult)) {
    1198                 :         // Fall back to parsing as atom for short values
    1199             174 :         aResult.ParseStringOrAtom(aValue);
    1200                 :     }
    1201                 : 
    1202             184 :     return true;
    1203                 : }
    1204                 : 
    1205                 : const nsAttrName*
    1206               0 : nsXULElement::InternalGetExistingAttrNameFromQName(const nsAString& aStr) const
    1207                 : {
    1208                 :     const nsAttrName* attrName =
    1209               0 :         mAttrsAndChildren.GetExistingAttrNameFromQName(aStr);
    1210               0 :     if (attrName) {
    1211               0 :         return attrName;
    1212                 :     }
    1213                 : 
    1214               0 :     if (mPrototype) {
    1215                 :         PRUint32 i;
    1216               0 :         for (i = 0; i < mPrototype->mNumAttributes; ++i) {
    1217               0 :             attrName = &mPrototype->mAttributes[i].mName;
    1218               0 :             if (attrName->QualifiedNameEquals(aStr)) {
    1219               0 :                 return attrName;
    1220                 :             }
    1221                 :         }
    1222                 :     }
    1223                 : 
    1224               0 :     return nsnull;
    1225                 : }
    1226                 : 
    1227                 : bool
    1228               2 : nsXULElement::GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
    1229                 :                       nsAString& aResult) const
    1230                 : {
    1231               2 :     NS_ASSERTION(nsnull != aName, "must have attribute name");
    1232               2 :     NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
    1233                 :                  "must have a real namespace ID!");
    1234                 : 
    1235               2 :     const nsAttrValue* val = FindLocalOrProtoAttr(aNameSpaceID, aName);
    1236                 : 
    1237               2 :     if (!val) {
    1238                 :         // Since we are returning a success code we'd better do
    1239                 :         // something about the out parameters (someone may have
    1240                 :         // given us a non-empty string).
    1241               2 :         aResult.Truncate();
    1242               2 :         return false;
    1243                 :     }
    1244                 : 
    1245               0 :     val->ToString(aResult);
    1246                 : 
    1247               0 :     return true;
    1248                 : }
    1249                 : 
    1250                 : bool
    1251               2 : nsXULElement::HasAttr(PRInt32 aNameSpaceID, nsIAtom* aName) const
    1252                 : {
    1253               2 :     NS_ASSERTION(nsnull != aName, "must have attribute name");
    1254               2 :     NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
    1255                 :                  "must have a real namespace ID!");
    1256                 : 
    1257               2 :     return mAttrsAndChildren.GetAttr(aName, aNameSpaceID) ||
    1258               2 :            FindPrototypeAttribute(aNameSpaceID, aName);
    1259                 : }
    1260                 : 
    1261                 : bool
    1262            1221 : nsXULElement::AttrValueIs(PRInt32 aNameSpaceID,
    1263                 :                           nsIAtom* aName,
    1264                 :                           const nsAString& aValue,
    1265                 :                           nsCaseTreatment aCaseSensitive) const
    1266                 : {
    1267            1221 :   NS_ASSERTION(aName, "Must have attr name");
    1268            1221 :   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
    1269                 : 
    1270            1221 :   const nsAttrValue* val = FindLocalOrProtoAttr(aNameSpaceID, aName);
    1271            1221 :   return val && val->Equals(aValue, aCaseSensitive);
    1272                 : }
    1273                 : 
    1274                 : bool
    1275               0 : nsXULElement::AttrValueIs(PRInt32 aNameSpaceID,
    1276                 :                           nsIAtom* aName,
    1277                 :                           nsIAtom* aValue,
    1278                 :                           nsCaseTreatment aCaseSensitive) const
    1279                 : {
    1280               0 :   NS_ASSERTION(aName, "Must have attr name");
    1281               0 :   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
    1282               0 :   NS_ASSERTION(aValue, "Null value atom");
    1283                 : 
    1284               0 :   const nsAttrValue* val = FindLocalOrProtoAttr(aNameSpaceID, aName);
    1285               0 :   return val && val->Equals(aValue, aCaseSensitive);
    1286                 : }
    1287                 : 
    1288                 : PRInt32
    1289               0 : nsXULElement::FindAttrValueIn(PRInt32 aNameSpaceID,
    1290                 :                               nsIAtom* aName,
    1291                 :                               AttrValuesArray* aValues,
    1292                 :                               nsCaseTreatment aCaseSensitive) const
    1293                 : {
    1294               0 :   NS_ASSERTION(aName, "Must have attr name");
    1295               0 :   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
    1296               0 :   NS_ASSERTION(aValues, "Null value array");
    1297                 :   
    1298               0 :   const nsAttrValue* val = FindLocalOrProtoAttr(aNameSpaceID, aName);
    1299               0 :   if (val) {
    1300               0 :     for (PRInt32 i = 0; aValues[i]; ++i) {
    1301               0 :       if (val->Equals(*aValues[i], aCaseSensitive)) {
    1302               0 :         return i;
    1303                 :       }
    1304                 :     }
    1305               0 :     return ATTR_VALUE_NO_MATCH;
    1306                 :   }
    1307               0 :   return ATTR_MISSING;
    1308                 : }
    1309                 : 
    1310                 : nsresult
    1311               0 : nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, bool aNotify)
    1312                 : {
    1313                 :     // This doesn't call BeforeSetAttr/AfterSetAttr for now.
    1314                 :     
    1315               0 :     NS_ASSERTION(nsnull != aName, "must have attribute name");
    1316                 :     nsresult rv;
    1317                 : 
    1318                 :     // Because It's Hard to maintain a magic ``unset'' value in
    1319                 :     // the local attributes, we'll fault all the attributes,
    1320                 :     // unhook ourselves from the prototype, and then remove the
    1321                 :     // local copy of the attribute that we want to unset. In
    1322                 :     // other words, we'll become ``heavyweight''.
    1323                 :     //
    1324                 :     // We can avoid this if the attribute isn't in the prototype,
    1325                 :     // then we just need to remove it locally
    1326                 : 
    1327                 :     nsXULPrototypeAttribute *protoattr =
    1328               0 :         FindPrototypeAttribute(aNameSpaceID, aName);
    1329               0 :     if (protoattr) {
    1330                 :         // We've got an attribute on the prototype, so we need to
    1331                 :         // fully fault and remove the local copy.
    1332               0 :         rv = MakeHeavyweight();
    1333               0 :         NS_ENSURE_SUCCESS(rv, rv);
    1334                 :     }
    1335                 : 
    1336               0 :     nsIDocument* doc = GetCurrentDoc();
    1337               0 :     mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
    1338                 : 
    1339               0 :     bool isId = false;
    1340               0 :     if (aName == nsGkAtoms::id && aNameSpaceID == kNameSpaceID_None) {
    1341                 :       // Have to do this before clearing flag. See RemoveFromIdTable
    1342               0 :       RemoveFromIdTable();
    1343               0 :       isId = true;
    1344                 :     }
    1345                 : 
    1346               0 :     PRInt32 index = mAttrsAndChildren.IndexOfAttr(aName, aNameSpaceID);
    1347               0 :     if (index < 0) {
    1348               0 :         NS_ASSERTION(!protoattr, "we used to have a protoattr, we should now "
    1349                 :                                  "have a normal one");
    1350                 : 
    1351               0 :         return NS_OK;
    1352                 :     }
    1353                 : 
    1354               0 :     nsAutoString oldValue;
    1355               0 :     GetAttr(aNameSpaceID, aName, oldValue);
    1356                 : 
    1357               0 :     if (aNotify) {
    1358                 :         nsNodeUtils::AttributeWillChange(this, aNameSpaceID, aName,
    1359               0 :                                          nsIDOMMutationEvent::REMOVAL);
    1360                 :     }
    1361                 : 
    1362                 :     bool hasMutationListeners = aNotify &&
    1363                 :         nsContentUtils::HasMutationListeners(this,
    1364               0 :             NS_EVENT_BITS_MUTATION_ATTRMODIFIED, this);
    1365                 : 
    1366               0 :     nsCOMPtr<nsIDOMAttr> attrNode;
    1367               0 :     if (hasMutationListeners) {
    1368               0 :         nsAutoString ns;
    1369               0 :         nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
    1370               0 :         GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName),
    1371               0 :                                    getter_AddRefs(attrNode));
    1372                 :     }
    1373                 : 
    1374               0 :     nsDOMSlots *slots = GetExistingDOMSlots();
    1375               0 :     if (slots && slots->mAttributeMap) {
    1376               0 :       slots->mAttributeMap->DropAttribute(aNameSpaceID, aName);
    1377                 :     }
    1378                 : 
    1379                 :     // The id-handling code, and in the future possibly other code, need to
    1380                 :     // react to unexpected attribute changes.
    1381               0 :     nsMutationGuard::DidMutate();
    1382                 : 
    1383               0 :     nsAttrValue ignored;
    1384               0 :     rv = mAttrsAndChildren.RemoveAttrAt(index, ignored);
    1385               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1386                 : 
    1387                 :     // XXX if the RemoveAttrAt() call fails, we might end up having removed
    1388                 :     // the attribute from the attribute map even though the attribute is still
    1389                 :     // on the element
    1390                 :     // https://bugzilla.mozilla.org/show_bug.cgi?id=296205
    1391                 : 
    1392                 :     // Deal with modification of magical attributes that side-effect
    1393                 :     // other things.
    1394                 :     // XXX Know how to remove POPUP event listeners when an attribute is unset?
    1395                 : 
    1396               0 :     if (isId) {
    1397               0 :         ClearHasID();
    1398                 :     }
    1399                 : 
    1400               0 :     if (aNameSpaceID == kNameSpaceID_None) {
    1401               0 :         if (mNodeInfo->Equals(nsGkAtoms::window)) {
    1402               0 :             if (aName == nsGkAtoms::hidechrome) {
    1403               0 :                 HideWindowChrome(false);
    1404                 :             }
    1405               0 :             else if (aName == nsGkAtoms::chromemargin) {
    1406               0 :                 ResetChromeMargins();
    1407                 :             }
    1408                 :         }
    1409                 : 
    1410               0 :         if (doc && doc->GetRootElement() == this) {
    1411               0 :             if ((aName == nsGkAtoms::activetitlebarcolor ||
    1412                 :                  aName == nsGkAtoms::inactivetitlebarcolor)) {
    1413                 :                 // Use 0, 0, 0, 0 as the "none" color.
    1414               0 :                 SetTitlebarColor(NS_RGBA(0, 0, 0, 0), aName == nsGkAtoms::activetitlebarcolor);
    1415                 :             }
    1416               0 :             else if (aName == nsGkAtoms::localedir) {
    1417                 :                 // if the localedir changed on the root element, reset the document direction
    1418               0 :                 nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(doc);
    1419               0 :                 if (xuldoc) {
    1420               0 :                     xuldoc->ResetDocumentDirection();
    1421                 :                 }
    1422                 :             }
    1423               0 :             else if ((aName == nsGkAtoms::lwtheme ||
    1424                 :                       aName == nsGkAtoms::lwthemetextcolor)) {
    1425                 :                 // if the lwtheme changed, make sure to restyle appropriately
    1426               0 :                 nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(doc);
    1427               0 :                 if (xuldoc) {
    1428               0 :                     xuldoc->ResetDocumentLWTheme();
    1429               0 :                 }
    1430                 :             }
    1431               0 :             else if (aName == nsGkAtoms::drawintitlebar) {
    1432               0 :                 SetDrawsInTitlebar(false);
    1433                 :             }
    1434                 :         }
    1435                 : 
    1436                 :         // If the accesskey attribute is removed, unregister it here
    1437                 :         // Also see nsXULLabelFrame, nsBoxFrame and nsTextBoxFrame's AttributeChanged
    1438               0 :         if (aName == nsGkAtoms::accesskey || aName == nsGkAtoms::control) {
    1439               0 :             UnregisterAccessKey(oldValue);
    1440                 :         }
    1441                 : 
    1442                 :         // Check to see if the OBSERVES attribute is being unset.  If so, we
    1443                 :         // need to remove our broadcaster goop completely.
    1444               0 :         if (doc && (aName == nsGkAtoms::observes ||
    1445                 :                           aName == nsGkAtoms::command)) {
    1446               0 :             RemoveBroadcaster(oldValue);
    1447                 :         }
    1448                 :     }
    1449                 : 
    1450               0 :     if (doc) {
    1451                 :         nsRefPtr<nsXBLBinding> binding =
    1452               0 :             doc->BindingManager()->GetBinding(this);
    1453               0 :         if (binding)
    1454               0 :             binding->AttributeChanged(aName, aNameSpaceID, true, aNotify);
    1455                 : 
    1456                 :     }
    1457                 : 
    1458               0 :     UpdateState(aNotify);
    1459                 : 
    1460               0 :     if (aNotify) {
    1461                 :         nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
    1462               0 :                                       nsIDOMMutationEvent::REMOVAL);
    1463                 :     }
    1464                 : 
    1465               0 :     if (hasMutationListeners) {
    1466               0 :         nsMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED);
    1467                 : 
    1468               0 :         mutation.mRelatedNode = attrNode;
    1469               0 :         mutation.mAttrName = aName;
    1470                 : 
    1471               0 :         if (!oldValue.IsEmpty())
    1472               0 :           mutation.mPrevAttrValue = do_GetAtom(oldValue);
    1473               0 :         mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
    1474                 : 
    1475               0 :         mozAutoSubtreeModified subtree(OwnerDoc(), this);
    1476               0 :         (new nsAsyncDOMEvent(this, mutation))->RunDOMEventWhenSafe();
    1477                 :     }
    1478                 : 
    1479               0 :     return NS_OK;
    1480                 : }
    1481                 : 
    1482                 : void
    1483               0 : nsXULElement::RemoveBroadcaster(const nsAString & broadcasterId)
    1484                 : {
    1485               0 :     nsCOMPtr<nsIDOMXULDocument> xuldoc = do_QueryInterface(OwnerDoc());
    1486               0 :     if (xuldoc) {
    1487               0 :         nsCOMPtr<nsIDOMElement> broadcaster;
    1488               0 :         nsCOMPtr<nsIDOMDocument> domDoc (do_QueryInterface(xuldoc));
    1489               0 :         domDoc->GetElementById(broadcasterId, getter_AddRefs(broadcaster));
    1490               0 :         if (broadcaster) {
    1491               0 :             xuldoc->RemoveBroadcastListenerFor(broadcaster, this,
    1492               0 :               NS_LITERAL_STRING("*"));
    1493                 :         }
    1494                 :     }
    1495               0 : }
    1496                 : 
    1497                 : const nsAttrName*
    1498            2286 : nsXULElement::GetAttrNameAt(PRUint32 aIndex) const
    1499                 : {
    1500            2286 :     PRUint32 localCount = mAttrsAndChildren.AttrCount();
    1501            2286 :     PRUint32 protoCount = mPrototype ? mPrototype->mNumAttributes : 0;
    1502                 : 
    1503            2286 :     if (localCount > protoCount) {
    1504                 :         // More local than proto, put local first
    1505                 : 
    1506                 :         // Is the index low enough to just grab a local attr?
    1507            2286 :         if (aIndex < localCount) {
    1508            2286 :             return mAttrsAndChildren.AttrNameAt(aIndex);
    1509                 :         }
    1510                 : 
    1511               0 :         aIndex -= localCount;
    1512                 : 
    1513                 :         // Search though prototype attributes while skipping names that exist in
    1514                 :         // the local array.
    1515               0 :         for (PRUint32 i = 0; i < protoCount; i++) {
    1516               0 :             const nsAttrName* name = &mPrototype->mAttributes[i].mName;
    1517               0 :             if (mAttrsAndChildren.GetAttr(name->LocalName(), name->NamespaceID())) {
    1518               0 :                 aIndex++;
    1519                 :             }
    1520               0 :             if (i == aIndex) {
    1521               0 :                 return name;
    1522                 :             }
    1523                 :         }
    1524                 :     }
    1525                 :     else {
    1526                 :         // More proto than local, put proto first
    1527                 : 
    1528                 :         // Is the index low enough to just grab a proto attr?
    1529               0 :         if (aIndex < protoCount) {
    1530               0 :             return &mPrototype->mAttributes[aIndex].mName;
    1531                 :         }
    1532                 : 
    1533               0 :         aIndex -= protoCount;
    1534                 : 
    1535                 :         // Search though local attributes while skipping names that exist in
    1536                 :         // the prototype array.
    1537               0 :         for (PRUint32 i = 0; i < localCount; i++) {
    1538               0 :             const nsAttrName* name = mAttrsAndChildren.AttrNameAt(i);
    1539                 : 
    1540               0 :             for (PRUint32 j = 0; j < protoCount; j++) {
    1541               0 :                 if (mPrototype->mAttributes[j].mName.Equals(*name)) {
    1542               0 :                     aIndex++;
    1543               0 :                     break;
    1544                 :                 }
    1545                 :             }
    1546               0 :             if (i == aIndex) {
    1547               0 :                 return name;
    1548                 :             }
    1549                 :         }
    1550                 :     }
    1551                 : 
    1552               0 :     return nsnull;
    1553                 : }
    1554                 : 
    1555                 : PRUint32
    1556            1964 : nsXULElement::GetAttrCount() const
    1557                 : {
    1558            1964 :     PRUint32 localCount = mAttrsAndChildren.AttrCount();
    1559            1964 :     PRUint32 protoCount = mPrototype ? mPrototype->mNumAttributes : 0;
    1560                 : 
    1561            1964 :     if (localCount > protoCount) {
    1562                 :         // More local than proto, remove dups from proto array
    1563            1964 :         PRUint32 count = localCount;
    1564                 : 
    1565            1964 :         for (PRUint32 i = 0; i < protoCount; i++) {
    1566               0 :             const nsAttrName* name = &mPrototype->mAttributes[i].mName;
    1567               0 :             if (!mAttrsAndChildren.GetAttr(name->LocalName(), name->NamespaceID())) {
    1568               0 :                 count++;
    1569                 :             }
    1570                 :         }
    1571                 : 
    1572            1964 :         return count;
    1573                 :     }
    1574                 : 
    1575                 :     // More proto than local, remove dups from local array
    1576               0 :     PRUint32 count = protoCount;
    1577                 : 
    1578               0 :     for (PRUint32 i = 0; i < localCount; i++) {
    1579               0 :         const nsAttrName* name = mAttrsAndChildren.AttrNameAt(i);
    1580                 : 
    1581               0 :         count++;
    1582               0 :         for (PRUint32 j = 0; j < protoCount; j++) {
    1583               0 :             if (mPrototype->mAttributes[j].mName.Equals(*name)) {
    1584               0 :                 count--;
    1585               0 :                 break;
    1586                 :             }
    1587                 :         }
    1588                 :     }
    1589                 : 
    1590               0 :     return count;
    1591                 : }
    1592                 : 
    1593                 : void
    1594               0 : nsXULElement::DestroyContent()
    1595                 : {
    1596               0 :     nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingDOMSlots());
    1597               0 :     if (slots) {
    1598               0 :         NS_IF_RELEASE(slots->mControllers);
    1599               0 :         if (slots->mFrameLoader) {
    1600               0 :             slots->mFrameLoader->Destroy();
    1601               0 :             slots->mFrameLoader = nsnull;
    1602                 :         }
    1603                 :     }
    1604                 : 
    1605               0 :     nsStyledElement::DestroyContent();
    1606               0 : }
    1607                 : 
    1608                 : #ifdef DEBUG
    1609                 : void
    1610               0 : nsXULElement::List(FILE* out, PRInt32 aIndent) const
    1611                 : {
    1612               0 :     nsCString prefix("XUL");
    1613               0 :     if (HasSlots()) {
    1614               0 :       prefix.Append('*');
    1615                 :     }
    1616               0 :     prefix.Append(' ');
    1617                 : 
    1618               0 :     nsStyledElement::List(out, aIndent, prefix);
    1619               0 : }
    1620                 : #endif
    1621                 : 
    1622                 : nsresult
    1623               0 : nsXULElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
    1624                 : {
    1625               0 :     aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119
    1626               0 :     nsIAtom* tag = Tag();
    1627               0 :     if (IsRootOfNativeAnonymousSubtree() &&
    1628                 :         (tag == nsGkAtoms::scrollbar || tag == nsGkAtoms::scrollcorner) &&
    1629                 :         (aVisitor.mEvent->message == NS_MOUSE_CLICK ||
    1630                 :          aVisitor.mEvent->message == NS_MOUSE_DOUBLECLICK ||
    1631                 :          aVisitor.mEvent->message == NS_XUL_COMMAND ||
    1632                 :          aVisitor.mEvent->message == NS_CONTEXTMENU ||
    1633                 :          aVisitor.mEvent->message == NS_DRAGDROP_START ||
    1634                 :          aVisitor.mEvent->message == NS_DRAGDROP_GESTURE)) {
    1635                 :         // Don't propagate these events from native anonymous scrollbar.
    1636               0 :         aVisitor.mCanHandle = true;
    1637               0 :         aVisitor.mParentTarget = nsnull;
    1638               0 :         return NS_OK;
    1639                 :     }
    1640               0 :     if (aVisitor.mEvent->message == NS_XUL_COMMAND &&
    1641                 :         aVisitor.mEvent->eventStructType == NS_INPUT_EVENT &&
    1642               0 :         aVisitor.mEvent->originalTarget == static_cast<nsIContent*>(this) &&
    1643                 :         tag != nsGkAtoms::command) {
    1644                 :         // Check that we really have an xul command event. That will be handled
    1645                 :         // in a special way.
    1646                 :         nsCOMPtr<nsIDOMXULCommandEvent> xulEvent =
    1647               0 :             do_QueryInterface(aVisitor.mDOMEvent);
    1648                 :         // See if we have a command elt.  If so, we execute on the command
    1649                 :         // instead of on our content element.
    1650               0 :         nsAutoString command;
    1651               0 :         if (xulEvent && GetAttr(kNameSpaceID_None, nsGkAtoms::command, command) &&
    1652               0 :             !command.IsEmpty()) {
    1653                 :             // Stop building the event target chain for the original event.
    1654                 :             // We don't want it to propagate to any DOM nodes.
    1655               0 :             aVisitor.mCanHandle = false;
    1656                 : 
    1657                 :             // XXX sXBL/XBL2 issue! Owner or current document?
    1658               0 :             nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(GetCurrentDoc()));
    1659               0 :             NS_ENSURE_STATE(domDoc);
    1660               0 :             nsCOMPtr<nsIDOMElement> commandElt;
    1661               0 :             domDoc->GetElementById(command, getter_AddRefs(commandElt));
    1662               0 :             nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt));
    1663               0 :             if (commandContent) {
    1664                 :                 // Create a new command event to dispatch to the element
    1665                 :                 // pointed to by the command attribute.  The new event's
    1666                 :                 // sourceEvent will be the original command event that we're
    1667                 :                 // handling.
    1668                 :                 nsCOMPtr<nsIDOMNSEvent> nsevent =
    1669               0 :                     do_QueryInterface(aVisitor.mDOMEvent);
    1670               0 :                 while (nsevent) {
    1671               0 :                     nsCOMPtr<nsIDOMEventTarget> oTarget;
    1672               0 :                     nsevent->GetOriginalTarget(getter_AddRefs(oTarget));
    1673               0 :                     NS_ENSURE_STATE(!SameCOMIdentity(oTarget, commandContent));
    1674               0 :                     nsCOMPtr<nsIDOMEvent> tmp;
    1675                 :                     nsCOMPtr<nsIDOMXULCommandEvent> commandEvent =
    1676               0 :                         do_QueryInterface(nsevent);
    1677               0 :                     if (commandEvent) {
    1678               0 :                         commandEvent->GetSourceEvent(getter_AddRefs(tmp));
    1679                 :                     }
    1680               0 :                     nsevent = do_QueryInterface(tmp);
    1681                 :                 }
    1682                 : 
    1683                 :                 nsInputEvent* orig =
    1684               0 :                     static_cast<nsInputEvent*>(aVisitor.mEvent);
    1685                 :                 nsContentUtils::DispatchXULCommand(
    1686                 :                   commandContent,
    1687                 :                   NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
    1688                 :                   aVisitor.mDOMEvent,
    1689                 :                   nsnull,
    1690                 :                   orig->isControl,
    1691                 :                   orig->isAlt,
    1692                 :                   orig->isShift,
    1693               0 :                   orig->isMeta);
    1694                 :             } else {
    1695               0 :                 NS_WARNING("A XUL element is attached to a command that doesn't exist!\n");
    1696                 :             }
    1697               0 :             return NS_OK;
    1698                 :         }
    1699                 :     }
    1700                 : 
    1701               0 :     return nsStyledElement::PreHandleEvent(aVisitor);
    1702                 : }
    1703                 : 
    1704                 : // XXX This _should_ be an implementation method, _not_ publicly exposed :-(
    1705                 : NS_IMETHODIMP
    1706               0 : nsXULElement::GetResource(nsIRDFResource** aResource)
    1707                 : {
    1708               0 :     nsAutoString id;
    1709               0 :     GetAttr(kNameSpaceID_None, nsGkAtoms::ref, id);
    1710               0 :     if (id.IsEmpty()) {
    1711               0 :         GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
    1712                 :     }
    1713                 : 
    1714               0 :     if (!id.IsEmpty()) {
    1715               0 :         return nsXULContentUtils::RDFService()->
    1716               0 :             GetUnicodeResource(id, aResource);
    1717                 :     }
    1718               0 :     *aResource = nsnull;
    1719                 : 
    1720               0 :     return NS_OK;
    1721                 : }
    1722                 : 
    1723                 : 
    1724                 : NS_IMETHODIMP
    1725               0 : nsXULElement::GetDatabase(nsIRDFCompositeDataSource** aDatabase)
    1726                 : {
    1727               0 :     nsCOMPtr<nsIXULTemplateBuilder> builder;
    1728               0 :     GetBuilder(getter_AddRefs(builder));
    1729                 : 
    1730               0 :     if (builder)
    1731               0 :         builder->GetDatabase(aDatabase);
    1732                 :     else
    1733               0 :         *aDatabase = nsnull;
    1734                 : 
    1735               0 :     return NS_OK;
    1736                 : }
    1737                 : 
    1738                 : 
    1739                 : NS_IMETHODIMP
    1740               0 : nsXULElement::GetBuilder(nsIXULTemplateBuilder** aBuilder)
    1741                 : {
    1742               0 :     *aBuilder = nsnull;
    1743                 : 
    1744                 :     // XXX sXBL/XBL2 issue! Owner or current document?
    1745               0 :     nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(GetCurrentDoc());
    1746               0 :     if (xuldoc)
    1747               0 :         xuldoc->GetTemplateBuilderFor(this, aBuilder);
    1748                 : 
    1749               0 :     return NS_OK;
    1750                 : }
    1751                 : 
    1752                 : 
    1753                 : //----------------------------------------------------------------------
    1754                 : // Implementation methods
    1755                 : 
    1756                 : // XXX DoGetID and DoGetClasses must be defined here because we have proto
    1757                 : // attributes.
    1758                 : nsIAtom*
    1759              30 : nsXULElement::DoGetID() const
    1760                 : {
    1761              30 :     NS_ASSERTION(HasID(), "Unexpected call");
    1762                 :     const nsAttrValue* attr =
    1763              30 :         FindLocalOrProtoAttr(kNameSpaceID_None, nsGkAtoms::id);
    1764                 : 
    1765                 :     // We need the nullcheck here because during unlink the prototype loses
    1766                 :     // all of its attributes. We might want to change that.
    1767                 :     // The nullcheck would also be needed if we make UnsetAttr use
    1768                 :     // nsGenericElement::UnsetAttr as that calls out to various code between
    1769                 :     // removing the attribute and calling ClearHasID().
    1770                 : 
    1771              30 :     return attr ? attr->GetAtomValue() : nsnull;
    1772                 : }
    1773                 : 
    1774                 : const nsAttrValue*
    1775               0 : nsXULElement::DoGetClasses() const
    1776                 : {
    1777               0 :     NS_ASSERTION(HasFlag(NODE_MAY_HAVE_CLASS), "Unexpected call");
    1778               0 :     return FindLocalOrProtoAttr(kNameSpaceID_None, nsGkAtoms::_class);
    1779                 : }
    1780                 : 
    1781                 : NS_IMETHODIMP
    1782               0 : nsXULElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
    1783                 : {
    1784               0 :     return NS_OK;
    1785                 : }
    1786                 : 
    1787                 : css::StyleRule*
    1788               0 : nsXULElement::GetInlineStyleRule()
    1789                 : {
    1790               0 :     if (!MayHaveStyle()) {
    1791               0 :         return nsnull;
    1792                 :     }
    1793                 :     // Fetch the cached style rule from the attributes.
    1794               0 :     const nsAttrValue* attrVal = FindLocalOrProtoAttr(kNameSpaceID_None, nsGkAtoms::style);
    1795                 : 
    1796               0 :     if (attrVal && attrVal->Type() == nsAttrValue::eCSSStyleRule) {
    1797               0 :         return attrVal->GetCSSStyleRuleValue();
    1798                 :     }
    1799                 : 
    1800               0 :     return nsnull;
    1801                 : }
    1802                 : 
    1803                 : nsChangeHint
    1804               0 : nsXULElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
    1805                 :                                      PRInt32 aModType) const
    1806                 : {
    1807               0 :     nsChangeHint retval(NS_STYLE_HINT_NONE);
    1808                 : 
    1809               0 :     if (aAttribute == nsGkAtoms::value &&
    1810                 :         (aModType == nsIDOMMutationEvent::REMOVAL ||
    1811                 :          aModType == nsIDOMMutationEvent::ADDITION)) {
    1812               0 :       nsIAtom *tag = Tag();
    1813               0 :       if (tag == nsGkAtoms::label || tag == nsGkAtoms::description)
    1814                 :         // Label and description dynamically morph between a normal
    1815                 :         // block and a cropping single-line XUL text frame.  If the
    1816                 :         // value attribute is being added or removed, then we need to
    1817                 :         // return a hint of frame change.  (See bugzilla bug 95475 for
    1818                 :         // details.)
    1819               0 :         retval = NS_STYLE_HINT_FRAMECHANGE;
    1820                 :     } else {
    1821                 :         // if left or top changes we reflow. This will happen in xul
    1822                 :         // containers that manage positioned children such as a stack.
    1823               0 :         if (nsGkAtoms::left == aAttribute || nsGkAtoms::top == aAttribute ||
    1824                 :             nsGkAtoms::right == aAttribute || nsGkAtoms::bottom == aAttribute ||
    1825                 :             nsGkAtoms::start == aAttribute || nsGkAtoms::end == aAttribute)
    1826               0 :             retval = NS_STYLE_HINT_REFLOW;
    1827                 :     }
    1828                 : 
    1829               0 :     return retval;
    1830                 : }
    1831                 : 
    1832                 : NS_IMETHODIMP_(bool)
    1833              66 : nsXULElement::IsAttributeMapped(const nsIAtom* aAttribute) const
    1834                 : {
    1835              66 :     return false;
    1836                 : }
    1837                 : 
    1838                 : // Controllers Methods
    1839                 : NS_IMETHODIMP
    1840               0 : nsXULElement::GetControllers(nsIControllers** aResult)
    1841                 : {
    1842               0 :     if (! Controllers()) {
    1843               0 :         nsDOMSlots* slots = DOMSlots();
    1844                 : 
    1845                 :         nsresult rv;
    1846                 :         rv = NS_NewXULControllers(nsnull, NS_GET_IID(nsIControllers),
    1847               0 :                                   reinterpret_cast<void**>(&slots->mControllers));
    1848                 : 
    1849               0 :         NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create a controllers");
    1850               0 :         if (NS_FAILED(rv)) return rv;
    1851                 :     }
    1852                 : 
    1853               0 :     *aResult = Controllers();
    1854               0 :     NS_IF_ADDREF(*aResult);
    1855               0 :     return NS_OK;
    1856                 : }
    1857                 : 
    1858                 : NS_IMETHODIMP
    1859               0 : nsXULElement::GetBoxObject(nsIBoxObject** aResult)
    1860                 : {
    1861               0 :   *aResult = nsnull;
    1862                 : 
    1863                 :   // XXX sXBL/XBL2 issue! Owner or current document?
    1864               0 :   return OwnerDoc()->GetBoxObjectFor(this, aResult);
    1865                 : }
    1866                 : 
    1867                 : // Methods for setting/getting attributes from nsIDOMXULElement
    1868                 : #define NS_IMPL_XUL_STRING_ATTR(_method, _atom)                     \
    1869                 :   NS_IMETHODIMP                                                     \
    1870                 :   nsXULElement::Get##_method(nsAString& aReturn)                    \
    1871                 :   {                                                                 \
    1872                 :     GetAttr(kNameSpaceID_None, nsGkAtoms::_atom, aReturn);         \
    1873                 :     return NS_OK;                                                   \
    1874                 :   }                                                                 \
    1875                 :   NS_IMETHODIMP                                                     \
    1876                 :   nsXULElement::Set##_method(const nsAString& aValue)               \
    1877                 :   {                                                                 \
    1878                 :     return SetAttr(kNameSpaceID_None, nsGkAtoms::_atom, aValue,    \
    1879                 :                    true);                                        \
    1880                 :   }
    1881                 : 
    1882                 : #define NS_IMPL_XUL_BOOL_ATTR(_method, _atom)                       \
    1883                 :   NS_IMETHODIMP                                                     \
    1884                 :   nsXULElement::Get##_method(bool* aResult)                       \
    1885                 :   {                                                                 \
    1886                 :     *aResult = BoolAttrIsTrue(nsGkAtoms::_atom);                   \
    1887                 :                                                                     \
    1888                 :     return NS_OK;                                                   \
    1889                 :   }                                                                 \
    1890                 :   NS_IMETHODIMP                                                     \
    1891                 :   nsXULElement::Set##_method(bool aValue)                         \
    1892                 :   {                                                                 \
    1893                 :     if (aValue)                                                     \
    1894                 :       SetAttr(kNameSpaceID_None, nsGkAtoms::_atom,                 \
    1895                 :               NS_LITERAL_STRING("true"), true);                  \
    1896                 :     else                                                            \
    1897                 :       UnsetAttr(kNameSpaceID_None, nsGkAtoms::_atom, true);     \
    1898                 :                                                                     \
    1899                 :     return NS_OK;                                                   \
    1900                 :   }
    1901                 : 
    1902                 : 
    1903               0 : NS_IMPL_XUL_STRING_ATTR(Id, id)
    1904               0 : NS_IMPL_XUL_STRING_ATTR(ClassName, _class)
    1905               0 : NS_IMPL_XUL_STRING_ATTR(Align, align)
    1906               0 : NS_IMPL_XUL_STRING_ATTR(Dir, dir)
    1907               0 : NS_IMPL_XUL_STRING_ATTR(Flex, flex)
    1908               0 : NS_IMPL_XUL_STRING_ATTR(FlexGroup, flexgroup)
    1909               0 : NS_IMPL_XUL_STRING_ATTR(Ordinal, ordinal)
    1910               0 : NS_IMPL_XUL_STRING_ATTR(Orient, orient)
    1911               0 : NS_IMPL_XUL_STRING_ATTR(Pack, pack)
    1912               0 : NS_IMPL_XUL_BOOL_ATTR(Hidden, hidden)
    1913               0 : NS_IMPL_XUL_BOOL_ATTR(Collapsed, collapsed)
    1914               0 : NS_IMPL_XUL_BOOL_ATTR(AllowEvents, allowevents)
    1915               0 : NS_IMPL_XUL_STRING_ATTR(Observes, observes)
    1916               0 : NS_IMPL_XUL_STRING_ATTR(Menu, menu)
    1917               0 : NS_IMPL_XUL_STRING_ATTR(ContextMenu, contextmenu)
    1918               0 : NS_IMPL_XUL_STRING_ATTR(Tooltip, tooltip)
    1919               0 : NS_IMPL_XUL_STRING_ATTR(Width, width)
    1920               0 : NS_IMPL_XUL_STRING_ATTR(Height, height)
    1921               0 : NS_IMPL_XUL_STRING_ATTR(MinWidth, minwidth)
    1922               0 : NS_IMPL_XUL_STRING_ATTR(MinHeight, minheight)
    1923               0 : NS_IMPL_XUL_STRING_ATTR(MaxWidth, maxwidth)
    1924               0 : NS_IMPL_XUL_STRING_ATTR(MaxHeight, maxheight)
    1925               0 : NS_IMPL_XUL_STRING_ATTR(Persist, persist)
    1926               0 : NS_IMPL_XUL_STRING_ATTR(Left, left)
    1927               0 : NS_IMPL_XUL_STRING_ATTR(Top, top)
    1928               0 : NS_IMPL_XUL_STRING_ATTR(Datasources, datasources)
    1929               0 : NS_IMPL_XUL_STRING_ATTR(Ref, ref)
    1930               0 : NS_IMPL_XUL_STRING_ATTR(TooltipText, tooltiptext)
    1931               0 : NS_IMPL_XUL_STRING_ATTR(StatusText, statustext)
    1932                 : 
    1933                 : nsresult
    1934               0 : nsXULElement::EnsureLocalStyle()
    1935                 : {
    1936                 :     // Clone the prototype rule, if we don't have a local one.
    1937               0 :     if (mPrototype &&
    1938               0 :         !mAttrsAndChildren.GetAttr(nsGkAtoms::style, kNameSpaceID_None)) {
    1939                 : 
    1940                 :         nsXULPrototypeAttribute *protoattr =
    1941               0 :                   FindPrototypeAttribute(kNameSpaceID_None, nsGkAtoms::style);
    1942               0 :         if (protoattr && protoattr->mValue.Type() == nsAttrValue::eCSSStyleRule) {
    1943                 :             nsRefPtr<css::Rule> ruleClone =
    1944               0 :                 protoattr->mValue.GetCSSStyleRuleValue()->Clone();
    1945                 : 
    1946               0 :             nsString stringValue;
    1947               0 :             protoattr->mValue.ToString(stringValue);
    1948                 : 
    1949               0 :             nsAttrValue value;
    1950               0 :             nsRefPtr<css::StyleRule> styleRule = do_QueryObject(ruleClone);
    1951               0 :             value.SetTo(styleRule, &stringValue);
    1952                 : 
    1953                 :             nsresult rv =
    1954               0 :                 mAttrsAndChildren.SetAndTakeAttr(nsGkAtoms::style, value);
    1955               0 :             NS_ENSURE_SUCCESS(rv, rv);
    1956                 :         }
    1957                 :     }
    1958                 : 
    1959               0 :     return NS_OK;
    1960                 : }
    1961                 : 
    1962                 : nsresult
    1963             144 : nsXULElement::LoadSrc()
    1964                 : {
    1965                 :     // Allow frame loader only on objects for which a container box object
    1966                 :     // can be obtained.
    1967             144 :     nsIAtom* tag = Tag();
    1968             144 :     if (tag != nsGkAtoms::browser &&
    1969                 :         tag != nsGkAtoms::editor &&
    1970                 :         tag != nsGkAtoms::iframe) {
    1971             144 :         return NS_OK;
    1972                 :     }
    1973               0 :     if (!IsInDoc() ||
    1974               0 :         !OwnerDoc()->GetRootElement() ||
    1975               0 :         OwnerDoc()->GetRootElement()->
    1976               0 :             NodeInfo()->Equals(nsGkAtoms::overlay, kNameSpaceID_XUL)) {
    1977               0 :         return NS_OK;
    1978                 :     }
    1979               0 :     nsXULSlots* slots = static_cast<nsXULSlots*>(GetSlots());
    1980               0 :     NS_ENSURE_TRUE(slots, NS_ERROR_OUT_OF_MEMORY);
    1981               0 :     if (!slots->mFrameLoader) {
    1982                 :         // false as the last parameter so that xul:iframe/browser/editor
    1983                 :         // session history handling works like dynamic html:iframes.
    1984                 :         // Usually xul elements are used in chrome, which doesn't have
    1985                 :         // session history at all.
    1986               0 :         slots->mFrameLoader = nsFrameLoader::Create(this, false);
    1987               0 :         NS_ENSURE_TRUE(slots->mFrameLoader, NS_OK);
    1988                 :     }
    1989                 : 
    1990               0 :     return slots->mFrameLoader->LoadFrame();
    1991                 : }
    1992                 : 
    1993                 : nsresult
    1994               0 : nsXULElement::GetFrameLoader(nsIFrameLoader **aFrameLoader)
    1995                 : {
    1996               0 :     *aFrameLoader = GetFrameLoader().get();
    1997               0 :     return NS_OK;
    1998                 : }
    1999                 : 
    2000                 : already_AddRefed<nsFrameLoader>
    2001               0 : nsXULElement::GetFrameLoader()
    2002                 : {
    2003               0 :     nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingSlots());
    2004               0 :     if (!slots)
    2005               0 :         return nsnull;
    2006                 : 
    2007               0 :     nsFrameLoader* loader = slots->mFrameLoader;
    2008               0 :     NS_IF_ADDREF(loader);
    2009               0 :     return loader;
    2010                 : }
    2011                 : 
    2012                 : nsresult
    2013               0 : nsXULElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
    2014                 : {
    2015               0 :     nsCOMPtr<nsIContent> otherContent(do_QueryInterface(aOtherOwner));
    2016               0 :     NS_ENSURE_TRUE(otherContent, NS_ERROR_NOT_IMPLEMENTED);
    2017                 : 
    2018               0 :     nsXULElement* otherEl = FromContent(otherContent);
    2019               0 :     NS_ENSURE_TRUE(otherEl, NS_ERROR_NOT_IMPLEMENTED);
    2020                 : 
    2021               0 :     if (otherEl == this) {
    2022                 :         // nothing to do
    2023               0 :         return NS_OK;
    2024                 :     }
    2025                 : 
    2026               0 :     nsXULSlots *ourSlots = static_cast<nsXULSlots*>(GetExistingDOMSlots());
    2027                 :     nsXULSlots *otherSlots =
    2028               0 :         static_cast<nsXULSlots*>(otherEl->GetExistingDOMSlots());
    2029               0 :     if (!ourSlots || !ourSlots->mFrameLoader ||
    2030               0 :         !otherSlots || !otherSlots->mFrameLoader) {
    2031                 :         // Can't handle swapping when there is nothing to swap... yet.
    2032               0 :         return NS_ERROR_NOT_IMPLEMENTED;
    2033                 :     }
    2034                 : 
    2035                 :     return
    2036                 :         ourSlots->mFrameLoader->SwapWithOtherLoader(otherSlots->mFrameLoader,
    2037                 :                                                     ourSlots->mFrameLoader,
    2038               0 :                                                     otherSlots->mFrameLoader);
    2039                 : }
    2040                 : 
    2041                 : NS_IMETHODIMP
    2042               0 : nsXULElement::GetParentTree(nsIDOMXULMultiSelectControlElement** aTreeElement)
    2043                 : {
    2044               0 :     for (nsIContent* current = GetParent(); current;
    2045               0 :          current = current->GetParent()) {
    2046               0 :         if (current->NodeInfo()->Equals(nsGkAtoms::listbox,
    2047               0 :                                         kNameSpaceID_XUL)) {
    2048               0 :             CallQueryInterface(current, aTreeElement);
    2049                 :             // XXX returning NS_OK because that's what the code used to do;
    2050                 :             // is that the right thing, though?
    2051                 : 
    2052               0 :             return NS_OK;
    2053                 :         }
    2054                 :     }
    2055                 : 
    2056               0 :     return NS_OK;
    2057                 : }
    2058                 : 
    2059                 : NS_IMETHODIMP
    2060               0 : nsXULElement::Focus()
    2061                 : {
    2062               0 :     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    2063               0 :     nsCOMPtr<nsIDOMElement> elem = do_QueryObject(this);
    2064               0 :     return fm ? fm->SetFocus(this, 0) : NS_OK;
    2065                 : }
    2066                 : 
    2067                 : NS_IMETHODIMP
    2068               0 : nsXULElement::Blur()
    2069                 : {
    2070               0 :     if (!ShouldBlur(this))
    2071               0 :       return NS_OK;
    2072                 : 
    2073               0 :     nsIDocument* doc = GetCurrentDoc();
    2074               0 :     if (!doc)
    2075               0 :       return NS_OK;
    2076                 : 
    2077               0 :     nsIDOMWindow* win = doc->GetWindow();
    2078               0 :     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    2079               0 :     if (win && fm)
    2080               0 :       return fm->ClearFocus(win);
    2081               0 :     return NS_OK;
    2082                 : }
    2083                 : 
    2084                 : NS_IMETHODIMP
    2085               0 : nsXULElement::Click()
    2086                 : {
    2087               0 :   return ClickWithInputSource(nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN);
    2088                 : }
    2089                 : 
    2090                 : nsresult
    2091               0 : nsXULElement::ClickWithInputSource(PRUint16 aInputSource)
    2092                 : {
    2093               0 :     if (BoolAttrIsTrue(nsGkAtoms::disabled))
    2094               0 :         return NS_OK;
    2095                 : 
    2096               0 :     nsCOMPtr<nsIDocument> doc = GetCurrentDoc(); // Strong just in case
    2097               0 :     if (doc) {
    2098               0 :         nsCOMPtr<nsIPresShell> shell = doc->GetShell();
    2099               0 :         if (shell) {
    2100                 :             // strong ref to PresContext so events don't destroy it
    2101               0 :             nsRefPtr<nsPresContext> context = shell->GetPresContext();
    2102                 : 
    2103               0 :             bool isCallerChrome = nsContentUtils::IsCallerChrome();
    2104                 : 
    2105                 :             nsMouseEvent eventDown(isCallerChrome, NS_MOUSE_BUTTON_DOWN,
    2106               0 :                                    nsnull, nsMouseEvent::eReal);
    2107                 :             nsMouseEvent eventUp(isCallerChrome, NS_MOUSE_BUTTON_UP,
    2108               0 :                                  nsnull, nsMouseEvent::eReal);
    2109                 :             nsMouseEvent eventClick(isCallerChrome, NS_MOUSE_CLICK, nsnull,
    2110               0 :                                     nsMouseEvent::eReal);
    2111                 :             eventDown.inputSource = eventUp.inputSource = eventClick.inputSource 
    2112               0 :                                   = aInputSource;
    2113                 : 
    2114                 :             // send mouse down
    2115               0 :             nsEventStatus status = nsEventStatus_eIgnore;
    2116                 :             nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this),
    2117               0 :                                         context, &eventDown,  nsnull, &status);
    2118                 : 
    2119                 :             // send mouse up
    2120               0 :             status = nsEventStatus_eIgnore;  // reset status
    2121                 :             nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this),
    2122               0 :                                         context, &eventUp, nsnull, &status);
    2123                 : 
    2124                 :             // send mouse click
    2125               0 :             status = nsEventStatus_eIgnore;  // reset status
    2126                 :             nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this),
    2127               0 :                                         context, &eventClick, nsnull, &status);
    2128                 :         }
    2129                 :     }
    2130                 : 
    2131                 :     // oncommand is fired when an element is clicked...
    2132               0 :     return DoCommand();
    2133                 : }
    2134                 : 
    2135                 : NS_IMETHODIMP
    2136               0 : nsXULElement::DoCommand()
    2137                 : {
    2138               0 :     nsCOMPtr<nsIDocument> doc = GetCurrentDoc(); // strong just in case
    2139               0 :     if (doc) {
    2140               0 :         nsContentUtils::DispatchXULCommand(this, true);
    2141                 :     }
    2142                 : 
    2143               0 :     return NS_OK;
    2144                 : }
    2145                 : 
    2146                 : nsIContent *
    2147             756 : nsXULElement::GetBindingParent() const
    2148                 : {
    2149             756 :     return mBindingParent;
    2150                 : }
    2151                 : 
    2152                 : bool
    2153             750 : nsXULElement::IsNodeOfType(PRUint32 aFlags) const
    2154                 : {
    2155             750 :     return !(aFlags & ~eCONTENT);
    2156                 : }
    2157                 : 
    2158                 : static void
    2159               0 : PopupListenerPropertyDtor(void* aObject, nsIAtom* aPropertyName,
    2160                 :                           void* aPropertyValue, void* aData)
    2161                 : {
    2162                 :   nsIDOMEventListener* listener =
    2163               0 :     static_cast<nsIDOMEventListener*>(aPropertyValue);
    2164               0 :   if (!listener) {
    2165               0 :     return;
    2166                 :   }
    2167                 :   nsEventListenerManager* manager = static_cast<nsINode*>(aObject)->
    2168               0 :     GetListenerManager(false);
    2169               0 :   if (manager) {
    2170                 :     manager->RemoveEventListenerByType(listener,
    2171               0 :                                        NS_LITERAL_STRING("mousedown"),
    2172                 :                                        NS_EVENT_FLAG_BUBBLE |
    2173               0 :                                        NS_EVENT_FLAG_SYSTEM_EVENT);
    2174                 :     manager->RemoveEventListenerByType(listener,
    2175               0 :                                        NS_LITERAL_STRING("contextmenu"),
    2176                 :                                        NS_EVENT_FLAG_BUBBLE |
    2177               0 :                                        NS_EVENT_FLAG_SYSTEM_EVENT);
    2178                 :   }
    2179               0 :   NS_RELEASE(listener);
    2180                 : }
    2181                 : 
    2182                 : nsresult
    2183               0 : nsXULElement::AddPopupListener(nsIAtom* aName)
    2184                 : {
    2185                 :     // Add a popup listener to the element
    2186                 :     bool isContext = (aName == nsGkAtoms::context ||
    2187               0 :                         aName == nsGkAtoms::contextmenu);
    2188                 :     nsIAtom* listenerAtom = isContext ?
    2189                 :                             nsGkAtoms::contextmenulistener :
    2190               0 :                             nsGkAtoms::popuplistener;
    2191                 : 
    2192                 :     nsCOMPtr<nsIDOMEventListener> popupListener =
    2193               0 :         static_cast<nsIDOMEventListener*>(GetProperty(listenerAtom));
    2194               0 :     if (popupListener) {
    2195                 :         // Popup listener is already installed.
    2196               0 :         return NS_OK;
    2197                 :     }
    2198                 : 
    2199               0 :     popupListener = new nsXULPopupListener(this, isContext);
    2200                 : 
    2201                 :     // Add the popup as a listener on this element.
    2202               0 :     nsEventListenerManager* manager = GetListenerManager(true);
    2203               0 :     NS_ENSURE_TRUE(manager, NS_ERROR_FAILURE);
    2204                 :     nsresult rv = SetProperty(listenerAtom, popupListener,
    2205               0 :                               PopupListenerPropertyDtor, true);
    2206               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2207                 :     // Want the property to have a reference to the listener.
    2208               0 :     nsIDOMEventListener* listener = nsnull;
    2209               0 :     popupListener.swap(listener);
    2210                 : 
    2211               0 :     if (isContext) {
    2212                 :       manager->AddEventListenerByType(listener,
    2213               0 :                                       NS_LITERAL_STRING("contextmenu"),
    2214                 :                                       NS_EVENT_FLAG_BUBBLE |
    2215               0 :                                       NS_EVENT_FLAG_SYSTEM_EVENT);
    2216                 :     } else {
    2217                 :       manager->AddEventListenerByType(listener,
    2218               0 :                                       NS_LITERAL_STRING("mousedown"),
    2219                 :                                       NS_EVENT_FLAG_BUBBLE |
    2220               0 :                                       NS_EVENT_FLAG_SYSTEM_EVENT);
    2221                 :     }
    2222               0 :     return NS_OK;
    2223                 : }
    2224                 : 
    2225                 : nsEventStates
    2226             328 : nsXULElement::IntrinsicState() const
    2227                 : {
    2228             328 :     nsEventStates state = nsStyledElement::IntrinsicState();
    2229                 : 
    2230             328 :     if (IsReadWriteTextElement()) {
    2231               0 :         state |= NS_EVENT_STATE_MOZ_READWRITE;
    2232               0 :         state &= ~NS_EVENT_STATE_MOZ_READONLY;
    2233                 :     }
    2234                 : 
    2235                 :     return state;
    2236                 : }
    2237                 : 
    2238                 : //----------------------------------------------------------------------
    2239                 : 
    2240                 : nsGenericElement::nsAttrInfo
    2241            1253 : nsXULElement::GetAttrInfo(PRInt32 aNamespaceID, nsIAtom *aName) const
    2242                 : {
    2243                 : 
    2244            1253 :     nsAttrInfo info(nsStyledElement::GetAttrInfo(aNamespaceID, aName));
    2245            1253 :     if (!info.mValue) {
    2246                 :         nsXULPrototypeAttribute *protoattr =
    2247             405 :             FindPrototypeAttribute(aNamespaceID, aName);
    2248             405 :         if (protoattr) {
    2249               0 :             return nsAttrInfo(&protoattr->mName, &protoattr->mValue);
    2250                 :         }
    2251                 :     }
    2252                 : 
    2253            1253 :     return info;
    2254                 : }
    2255                 : 
    2256                 : 
    2257                 : nsXULPrototypeAttribute *
    2258             407 : nsXULElement::FindPrototypeAttribute(PRInt32 aNamespaceID,
    2259                 :                                      nsIAtom* aLocalName) const
    2260                 : {
    2261             407 :     if (!mPrototype) {
    2262             407 :         return nsnull;
    2263                 :     }
    2264                 : 
    2265               0 :     PRUint32 i, count = mPrototype->mNumAttributes;
    2266               0 :     if (aNamespaceID == kNameSpaceID_None) {
    2267                 :         // Common case so optimize for this
    2268               0 :         for (i = 0; i < count; ++i) {
    2269               0 :             nsXULPrototypeAttribute *protoattr = &mPrototype->mAttributes[i];
    2270               0 :             if (protoattr->mName.Equals(aLocalName)) {
    2271               0 :                 return protoattr;
    2272                 :             }
    2273                 :         }
    2274                 :     }
    2275                 :     else {
    2276               0 :         for (i = 0; i < count; ++i) {
    2277               0 :             nsXULPrototypeAttribute *protoattr = &mPrototype->mAttributes[i];
    2278               0 :             if (protoattr->mName.Equals(aLocalName, aNamespaceID)) {
    2279               0 :                 return protoattr;
    2280                 :             }
    2281                 :         }
    2282                 :     }
    2283                 : 
    2284               0 :     return nsnull;
    2285                 : }
    2286                 : 
    2287               0 : nsresult nsXULElement::MakeHeavyweight()
    2288                 : {
    2289               0 :     if (!mPrototype)
    2290               0 :         return NS_OK;           // already heavyweight
    2291                 : 
    2292               0 :     nsRefPtr<nsXULPrototypeElement> proto;
    2293               0 :     proto.swap(mPrototype);
    2294                 : 
    2295               0 :     bool hadAttributes = mAttrsAndChildren.AttrCount() > 0;
    2296                 : 
    2297                 :     PRUint32 i;
    2298                 :     nsresult rv;
    2299               0 :     for (i = 0; i < proto->mNumAttributes; ++i) {
    2300               0 :         nsXULPrototypeAttribute* protoattr = &proto->mAttributes[i];
    2301                 : 
    2302                 :         // We might have a local value for this attribute, in which case
    2303                 :         // we don't want to copy the prototype's value.
    2304               0 :         if (hadAttributes &&
    2305                 :             mAttrsAndChildren.GetAttr(protoattr->mName.LocalName(),
    2306               0 :                                       protoattr->mName.NamespaceID())) {
    2307               0 :             continue;
    2308                 :         }
    2309                 : 
    2310               0 :         nsAttrValue attrValue;
    2311                 :         
    2312                 :         // Style rules need to be cloned.
    2313               0 :         if (protoattr->mValue.Type() == nsAttrValue::eCSSStyleRule) {
    2314                 :             nsRefPtr<css::Rule> ruleClone =
    2315               0 :                 protoattr->mValue.GetCSSStyleRuleValue()->Clone();
    2316                 : 
    2317               0 :             nsString stringValue;
    2318               0 :             protoattr->mValue.ToString(stringValue);
    2319                 : 
    2320               0 :             nsRefPtr<css::StyleRule> styleRule = do_QueryObject(ruleClone);
    2321               0 :             attrValue.SetTo(styleRule, &stringValue);
    2322                 :         }
    2323                 :         else {
    2324               0 :             attrValue.SetTo(protoattr->mValue);
    2325                 :         }
    2326                 : 
    2327                 :         // XXX we might wanna have a SetAndTakeAttr that takes an nsAttrName
    2328               0 :         if (protoattr->mName.IsAtom()) {
    2329               0 :             rv = mAttrsAndChildren.SetAndTakeAttr(protoattr->mName.Atom(), attrValue);
    2330                 :         }
    2331                 :         else {
    2332                 :             rv = mAttrsAndChildren.SetAndTakeAttr(protoattr->mName.NodeInfo(),
    2333               0 :                                                   attrValue);
    2334                 :         }
    2335               0 :         NS_ENSURE_SUCCESS(rv, rv);
    2336                 :     }
    2337               0 :     return NS_OK;
    2338                 : }
    2339                 : 
    2340                 : nsresult
    2341               0 : nsXULElement::HideWindowChrome(bool aShouldHide)
    2342                 : {
    2343               0 :     nsIDocument* doc = GetCurrentDoc();
    2344               0 :     if (!doc || doc->GetRootElement() != this)
    2345               0 :       return NS_ERROR_UNEXPECTED;
    2346                 : 
    2347                 :     // only top level chrome documents can hide the window chrome
    2348               0 :     if (!doc->IsRootDisplayDocument())
    2349               0 :       return NS_OK;
    2350                 : 
    2351               0 :     nsIPresShell *shell = doc->GetShell();
    2352                 : 
    2353               0 :     if (shell) {
    2354               0 :         nsIFrame* frame = GetPrimaryFrame();
    2355                 : 
    2356               0 :         nsPresContext *presContext = shell->GetPresContext();
    2357                 : 
    2358               0 :         if (frame && presContext && presContext->IsChrome()) {
    2359               0 :             nsIView* view = frame->GetClosestView();
    2360                 : 
    2361               0 :             if (view) {
    2362               0 :                 nsIWidget* w = view->GetWidget();
    2363               0 :                 NS_ENSURE_STATE(w);
    2364               0 :                 w->HideWindowChrome(aShouldHide);
    2365                 :             }
    2366                 :         }
    2367                 :     }
    2368                 : 
    2369               0 :     return NS_OK;
    2370                 : }
    2371                 : 
    2372                 : nsIWidget*
    2373               0 : nsXULElement::GetWindowWidget()
    2374                 : {
    2375               0 :     nsIDocument* doc = GetCurrentDoc();
    2376                 : 
    2377                 :     // only top level chrome documents can set the titlebar color
    2378               0 :     if (doc->IsRootDisplayDocument()) {
    2379               0 :         nsCOMPtr<nsISupports> container = doc->GetContainer();
    2380               0 :         nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(container);
    2381               0 :         if (baseWindow) {
    2382               0 :             nsCOMPtr<nsIWidget> mainWidget;
    2383               0 :             baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
    2384               0 :             return mainWidget;
    2385                 :         }
    2386                 :     }
    2387               0 :     return nsnull;
    2388                 : }
    2389                 : 
    2390                 : void
    2391               0 : nsXULElement::SetTitlebarColor(nscolor aColor, bool aActive)
    2392                 : {
    2393               0 :     nsIWidget* mainWidget = GetWindowWidget();
    2394               0 :     if (mainWidget) {
    2395               0 :         mainWidget->SetWindowTitlebarColor(aColor, aActive);
    2396                 :     }
    2397               0 : }
    2398                 : 
    2399                 : class SetDrawInTitleBarEvent : public nsRunnable
    2400               0 : {
    2401                 : public:
    2402               0 :   SetDrawInTitleBarEvent(nsIWidget* aWidget, bool aState)
    2403                 :     : mWidget(aWidget)
    2404               0 :     , mState(aState)
    2405               0 :   {}
    2406                 : 
    2407               0 :   NS_IMETHOD Run() {
    2408               0 :     NS_ASSERTION(mWidget, "You shouldn't call this runnable with a null widget!");
    2409                 : 
    2410               0 :     mWidget->SetDrawsInTitlebar(mState);
    2411               0 :     return NS_OK;
    2412                 :   }
    2413                 : 
    2414                 : private:
    2415                 :   nsCOMPtr<nsIWidget> mWidget;
    2416                 :   bool mState;
    2417                 : };
    2418                 : 
    2419                 : void
    2420               0 : nsXULElement::SetDrawsInTitlebar(bool aState)
    2421                 : {
    2422               0 :     nsIWidget* mainWidget = GetWindowWidget();
    2423               0 :     if (mainWidget) {
    2424               0 :         nsContentUtils::AddScriptRunner(new SetDrawInTitleBarEvent(mainWidget, aState));
    2425                 :     }
    2426               0 : }
    2427                 : 
    2428                 : class MarginSetter : public nsRunnable
    2429               0 : {
    2430                 : public:
    2431               0 :     MarginSetter(nsIWidget* aWidget) :
    2432               0 :         mWidget(aWidget), mMargin(-1, -1, -1, -1)
    2433               0 :     {}
    2434               0 :     MarginSetter(nsIWidget *aWidget, const nsIntMargin& aMargin) :
    2435               0 :         mWidget(aWidget), mMargin(aMargin)
    2436               0 :     {}
    2437                 : 
    2438               0 :     NS_IMETHOD Run()
    2439                 :     {
    2440                 :         // SetNonClientMargins can dispatch native events, hence doing
    2441                 :         // it off a script runner.
    2442               0 :         mWidget->SetNonClientMargins(mMargin);
    2443               0 :         return NS_OK;
    2444                 :     }
    2445                 : 
    2446                 : private:
    2447                 :     nsCOMPtr<nsIWidget> mWidget;
    2448                 :     nsIntMargin mMargin;
    2449                 : };
    2450                 : 
    2451                 : void
    2452               0 : nsXULElement::SetChromeMargins(const nsAttrValue* aValue)
    2453                 : {
    2454               0 :     if (!aValue)
    2455               0 :         return;
    2456                 : 
    2457               0 :     nsIWidget* mainWidget = GetWindowWidget();
    2458               0 :     if (!mainWidget)
    2459               0 :         return;
    2460                 : 
    2461                 :     // top, right, bottom, left - see nsAttrValue
    2462               0 :     nsIntMargin margins;
    2463               0 :     bool gotMargins = false;
    2464                 : 
    2465               0 :     if (aValue->Type() == nsAttrValue::eIntMarginValue) {
    2466               0 :         gotMargins = aValue->GetIntMarginValue(margins);
    2467                 :     } else {
    2468               0 :         nsAutoString tmp;
    2469               0 :         aValue->ToString(tmp);
    2470               0 :         gotMargins = nsContentUtils::ParseIntMarginValue(tmp, margins);
    2471                 :     }
    2472               0 :     if (gotMargins) {
    2473               0 :         nsContentUtils::AddScriptRunner(new MarginSetter(mainWidget, margins));
    2474                 :     }
    2475                 : }
    2476                 : 
    2477                 : void
    2478               0 : nsXULElement::ResetChromeMargins()
    2479                 : {
    2480               0 :     nsIWidget* mainWidget = GetWindowWidget();
    2481               0 :     if (!mainWidget)
    2482               0 :         return;
    2483                 :     // See nsIWidget
    2484               0 :     nsContentUtils::AddScriptRunner(new MarginSetter(mainWidget));
    2485                 : }
    2486                 : 
    2487                 : bool
    2488               0 : nsXULElement::BoolAttrIsTrue(nsIAtom* aName)
    2489                 : {
    2490                 :     const nsAttrValue* attr =
    2491               0 :         FindLocalOrProtoAttr(kNameSpaceID_None, aName);
    2492                 : 
    2493               0 :     return attr && attr->Type() == nsAttrValue::eAtom &&
    2494               0 :            attr->GetAtomValue() == nsGkAtoms::_true;
    2495                 : }
    2496                 : 
    2497                 : void
    2498               0 : nsXULElement::RecompileScriptEventListeners()
    2499                 : {
    2500               0 :     PRInt32 i, count = mAttrsAndChildren.AttrCount();
    2501               0 :     bool haveLocalAttributes = (count > 0);
    2502               0 :     for (i = 0; i < count; ++i) {
    2503               0 :         const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
    2504                 : 
    2505                 :         // Eventlistenener-attributes are always in the null namespace
    2506               0 :         if (!name->IsAtom()) {
    2507               0 :             continue;
    2508                 :         }
    2509                 : 
    2510               0 :         nsIAtom *attr = name->Atom();
    2511               0 :         if (!nsContentUtils::IsEventAttributeName(attr, EventNameType_XUL)) {
    2512               0 :             continue;
    2513                 :         }
    2514                 : 
    2515               0 :         nsAutoString value;
    2516               0 :         GetAttr(kNameSpaceID_None, attr, value);
    2517               0 :         AddScriptEventListener(attr, value, true);
    2518                 :     }
    2519                 : 
    2520               0 :     if (mPrototype) {
    2521                 :         // If we have a prototype, the node we are binding to should
    2522                 :         // have the same script-type - otherwise we will compile the
    2523                 :         // event handlers incorrectly.
    2524               0 :         NS_ASSERTION(mPrototype->mScriptTypeID == GetScriptTypeID(),
    2525                 :                      "Prototype and node confused about default language?");
    2526                 : 
    2527               0 :         count = mPrototype->mNumAttributes;
    2528               0 :         for (i = 0; i < count; ++i) {
    2529               0 :             const nsAttrName &name = mPrototype->mAttributes[i].mName;
    2530                 : 
    2531                 :             // Eventlistenener-attributes are always in the null namespace
    2532               0 :             if (!name.IsAtom()) {
    2533               0 :                 continue;
    2534                 :             }
    2535                 : 
    2536               0 :             nsIAtom *attr = name.Atom();
    2537                 : 
    2538                 :             // Don't clobber a locally modified attribute.
    2539               0 :             if (haveLocalAttributes && mAttrsAndChildren.GetAttr(attr)) {
    2540               0 :                 continue;
    2541                 :             }
    2542                 : 
    2543               0 :             if (!nsContentUtils::IsEventAttributeName(attr, EventNameType_XUL)) {
    2544               0 :                 continue;
    2545                 :             }
    2546                 : 
    2547               0 :             nsAutoString value;
    2548               0 :             GetAttr(kNameSpaceID_None, attr, value);
    2549               0 :             AddScriptEventListener(attr, value, true);
    2550                 :         }
    2551                 :     }
    2552               0 : }
    2553                 : 
    2554            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPrototypeNode)
    2555               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULPrototypeNode)
    2556               0 :     if (tmp->mType == nsXULPrototypeNode::eType_Element) {
    2557               0 :         static_cast<nsXULPrototypeElement*>(tmp)->Unlink();
    2558                 :     }
    2559               0 :     else if (tmp->mType == nsXULPrototypeNode::eType_Script) {
    2560               0 :         static_cast<nsXULPrototypeScript*>(tmp)->UnlinkJSObjects();
    2561                 :     }
    2562               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    2563               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULPrototypeNode)
    2564               0 :     if (tmp->mType == nsXULPrototypeNode::eType_Element) {
    2565                 :         nsXULPrototypeElement *elem =
    2566               0 :             static_cast<nsXULPrototypeElement*>(tmp);
    2567               0 :         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mNodeInfo");
    2568               0 :         cb.NoteXPCOMChild(elem->mNodeInfo);
    2569                 :         PRUint32 i;
    2570               0 :         for (i = 0; i < elem->mNumAttributes; ++i) {
    2571               0 :             const nsAttrName& name = elem->mAttributes[i].mName;
    2572               0 :             if (!name.IsAtom()) {
    2573               0 :                 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
    2574                 :                     "mAttributes[i].mName.NodeInfo()");
    2575               0 :                 cb.NoteXPCOMChild(name.NodeInfo());
    2576                 :             }
    2577                 :         }
    2578               0 :         for (i = 0; i < elem->mChildren.Length(); ++i) {
    2579               0 :             NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mChildren[i]");
    2580               0 :             cb.NoteXPCOMChild(elem->mChildren[i]);
    2581                 :         }
    2582                 :     }
    2583               0 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
    2584               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    2585               0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXULPrototypeNode)
    2586               0 :     if (tmp->mType == nsXULPrototypeNode::eType_Element) {
    2587                 :         nsXULPrototypeElement *elem =
    2588               0 :             static_cast<nsXULPrototypeElement*>(tmp);
    2589               0 :         if (elem->mHoldsScriptObject) {
    2590                 :             PRUint32 i;
    2591               0 :             for (i = 0; i < elem->mNumAttributes; ++i) {
    2592               0 :                 JSObject* handler = elem->mAttributes[i].mEventHandler;
    2593               0 :                 NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(elem->mScriptTypeID,
    2594                 :                                                         handler,
    2595                 :                                                         "mAttributes[i].mEventHandler")
    2596                 :             }
    2597                 :         }
    2598                 :     }
    2599               0 :     else if (tmp->mType == nsXULPrototypeNode::eType_Script) {
    2600                 :         nsXULPrototypeScript *script =
    2601               0 :             static_cast<nsXULPrototypeScript*>(tmp);
    2602               0 :         NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(script->mScriptObject.mLangID,
    2603                 :                                                 script->mScriptObject.mObject,
    2604                 :                                                 "mScriptObject.mObject")
    2605                 :     }
    2606               0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
    2607                 : 
    2608               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULPrototypeNode)
    2609               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULPrototypeNode)
    2610                 : 
    2611               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULPrototypeNode)
    2612               0 :     NS_INTERFACE_MAP_ENTRY(nsISupports)
    2613               0 : NS_INTERFACE_MAP_END
    2614                 : 
    2615                 : //----------------------------------------------------------------------
    2616                 : //
    2617                 : // nsXULPrototypeAttribute
    2618                 : //
    2619                 : 
    2620               0 : nsXULPrototypeAttribute::~nsXULPrototypeAttribute()
    2621                 : {
    2622               0 :     MOZ_COUNT_DTOR(nsXULPrototypeAttribute);
    2623               0 : }
    2624                 : 
    2625                 : 
    2626                 : //----------------------------------------------------------------------
    2627                 : //
    2628                 : // nsXULPrototypeElement
    2629                 : //
    2630                 : 
    2631                 : nsresult
    2632               0 : nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream,
    2633                 :                                  nsIScriptGlobalObject* aGlobal,
    2634                 :                                  const nsCOMArray<nsINodeInfo> *aNodeInfos)
    2635                 : {
    2636                 :     nsresult rv;
    2637                 : 
    2638                 :     // Write basic prototype data
    2639               0 :     rv = aStream->Write32(mType);
    2640                 : 
    2641                 :     // Write script language
    2642               0 :     rv |= aStream->Write32(mScriptTypeID);
    2643                 : 
    2644                 :     // Write Node Info
    2645               0 :     PRInt32 index = aNodeInfos->IndexOf(mNodeInfo);
    2646               0 :     NS_ASSERTION(index >= 0, "unknown nsINodeInfo index");
    2647               0 :     rv |= aStream->Write32(index);
    2648                 : 
    2649                 :     // Write Attributes
    2650               0 :     rv |= aStream->Write32(mNumAttributes);
    2651                 : 
    2652               0 :     nsAutoString attributeValue;
    2653                 :     PRUint32 i;
    2654               0 :     for (i = 0; i < mNumAttributes; ++i) {
    2655               0 :         nsCOMPtr<nsINodeInfo> ni;
    2656               0 :         if (mAttributes[i].mName.IsAtom()) {
    2657                 :             ni = mNodeInfo->NodeInfoManager()->
    2658               0 :                 GetNodeInfo(mAttributes[i].mName.Atom(), nsnull,
    2659                 :                             kNameSpaceID_None,
    2660               0 :                             nsIDOMNode::ATTRIBUTE_NODE);
    2661               0 :             NS_ASSERTION(ni, "the nodeinfo should already exist");
    2662                 :         }
    2663                 :         else {
    2664               0 :             ni = mAttributes[i].mName.NodeInfo();
    2665                 :         }
    2666                 : 
    2667               0 :         index = aNodeInfos->IndexOf(ni);
    2668               0 :         NS_ASSERTION(index >= 0, "unknown nsINodeInfo index");
    2669               0 :         rv |= aStream->Write32(index);
    2670                 : 
    2671               0 :         mAttributes[i].mValue.ToString(attributeValue);
    2672               0 :         rv |= aStream->WriteWStringZ(attributeValue.get());
    2673                 :     }
    2674                 : 
    2675                 :     // Now write children
    2676               0 :     rv |= aStream->Write32(PRUint32(mChildren.Length()));
    2677               0 :     for (i = 0; i < mChildren.Length(); i++) {
    2678               0 :         nsXULPrototypeNode* child = mChildren[i].get();
    2679               0 :         switch (child->mType) {
    2680                 :         case eType_Element:
    2681                 :         case eType_Text:
    2682                 :         case eType_PI:
    2683               0 :             rv |= child->Serialize(aStream, aGlobal, aNodeInfos);
    2684               0 :             break;
    2685                 :         case eType_Script:
    2686               0 :             rv |= aStream->Write32(child->mType);
    2687               0 :             nsXULPrototypeScript* script = static_cast<nsXULPrototypeScript*>(child);
    2688                 : 
    2689               0 :             rv |= aStream->Write32(script->mScriptObject.mLangID);
    2690                 : 
    2691               0 :             rv |= aStream->Write8(script->mOutOfLine);
    2692               0 :             if (! script->mOutOfLine) {
    2693               0 :                 rv |= script->Serialize(aStream, aGlobal, aNodeInfos);
    2694                 :             } else {
    2695                 :                 rv |= aStream->WriteCompoundObject(script->mSrcURI,
    2696                 :                                                    NS_GET_IID(nsIURI),
    2697               0 :                                                    true);
    2698                 : 
    2699               0 :                 if (script->mScriptObject.mObject) {
    2700                 :                     // This may return NS_OK without muxing script->mSrcURI's
    2701                 :                     // data into the cache file, in the case where that
    2702                 :                     // muxed document is already there (written by a prior
    2703                 :                     // session, or by an earlier cache episode during this
    2704                 :                     // session).
    2705               0 :                     rv |= script->SerializeOutOfLine(aStream, aGlobal);
    2706                 :                 }
    2707                 :             }
    2708               0 :             break;
    2709                 :         }
    2710                 :     }
    2711                 : 
    2712               0 :     return rv;
    2713                 : }
    2714                 : 
    2715                 : nsresult
    2716               0 : nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream,
    2717                 :                                    nsIScriptGlobalObject* aGlobal,
    2718                 :                                    nsIURI* aDocumentURI,
    2719                 :                                    const nsCOMArray<nsINodeInfo> *aNodeInfos)
    2720                 : {
    2721               0 :     NS_PRECONDITION(aNodeInfos, "missing nodeinfo array");
    2722                 :     nsresult rv;
    2723                 : 
    2724                 :     // Read script language
    2725               0 :     PRUint32 scriptId = 0;
    2726               0 :     rv = aStream->Read32(&scriptId);
    2727               0 :     mScriptTypeID = scriptId;
    2728                 : 
    2729                 :     // Read Node Info
    2730                 :     PRUint32 number;
    2731               0 :     rv |= aStream->Read32(&number);
    2732               0 :     mNodeInfo = aNodeInfos->SafeObjectAt(number);
    2733               0 :     if (!mNodeInfo)
    2734               0 :         return NS_ERROR_UNEXPECTED;
    2735                 : 
    2736                 :     // Read Attributes
    2737               0 :     rv |= aStream->Read32(&number);
    2738               0 :     mNumAttributes = PRInt32(number);
    2739                 : 
    2740                 :     PRUint32 i;
    2741               0 :     if (mNumAttributes > 0) {
    2742               0 :         mAttributes = new nsXULPrototypeAttribute[mNumAttributes];
    2743               0 :         if (! mAttributes)
    2744               0 :             return NS_ERROR_OUT_OF_MEMORY;
    2745                 : 
    2746               0 :         nsAutoString attributeValue;
    2747               0 :         for (i = 0; i < mNumAttributes; ++i) {
    2748               0 :             rv |= aStream->Read32(&number);
    2749               0 :             nsINodeInfo* ni = aNodeInfos->SafeObjectAt(number);
    2750               0 :             if (!ni)
    2751               0 :                 return NS_ERROR_UNEXPECTED;
    2752                 : 
    2753               0 :             mAttributes[i].mName.SetTo(ni);
    2754                 : 
    2755               0 :             rv |= aStream->ReadString(attributeValue);
    2756               0 :             rv |= SetAttrAt(i, attributeValue, aDocumentURI);
    2757                 :         }
    2758                 :     }
    2759                 : 
    2760               0 :     rv |= aStream->Read32(&number);
    2761               0 :     PRUint32 numChildren = PRInt32(number);
    2762                 : 
    2763               0 :     if (numChildren > 0) {
    2764               0 :         if (!mChildren.SetCapacity(numChildren))
    2765               0 :             return NS_ERROR_OUT_OF_MEMORY;
    2766                 : 
    2767               0 :         for (i = 0; i < numChildren; i++) {
    2768               0 :             rv |= aStream->Read32(&number);
    2769               0 :             Type childType = (Type)number;
    2770                 : 
    2771               0 :             nsRefPtr<nsXULPrototypeNode> child;
    2772                 : 
    2773               0 :             switch (childType) {
    2774                 :             case eType_Element:
    2775               0 :                 child = new nsXULPrototypeElement();
    2776               0 :                 if (! child)
    2777               0 :                     return NS_ERROR_OUT_OF_MEMORY;
    2778               0 :                 child->mType = childType;
    2779                 : 
    2780               0 :                 rv |= child->Deserialize(aStream, aGlobal, aDocumentURI,
    2781               0 :                                          aNodeInfos);
    2782               0 :                 break;
    2783                 :             case eType_Text:
    2784               0 :                 child = new nsXULPrototypeText();
    2785               0 :                 if (! child)
    2786               0 :                     return NS_ERROR_OUT_OF_MEMORY;
    2787               0 :                 child->mType = childType;
    2788                 : 
    2789               0 :                 rv |= child->Deserialize(aStream, aGlobal, aDocumentURI,
    2790               0 :                                          aNodeInfos);
    2791               0 :                 break;
    2792                 :             case eType_PI:
    2793               0 :                 child = new nsXULPrototypePI();
    2794               0 :                 if (! child)
    2795               0 :                     return NS_ERROR_OUT_OF_MEMORY;
    2796               0 :                 child->mType = childType;
    2797                 : 
    2798               0 :                 rv |= child->Deserialize(aStream, aGlobal, aDocumentURI,
    2799               0 :                                          aNodeInfos);
    2800               0 :                 break;
    2801                 :             case eType_Script: {
    2802               0 :                 PRUint32 langID = nsIProgrammingLanguage::UNKNOWN;
    2803               0 :                 rv |= aStream->Read32(&langID);
    2804                 : 
    2805                 :                 // language version/options obtained during deserialization.
    2806               0 :                 nsXULPrototypeScript* script = new nsXULPrototypeScript(langID, 0, 0);
    2807               0 :                 if (! script)
    2808               0 :                     return NS_ERROR_OUT_OF_MEMORY;
    2809               0 :                 child = script;
    2810               0 :                 child->mType = childType;
    2811                 : 
    2812               0 :                 rv |= aStream->ReadBoolean(&script->mOutOfLine);
    2813               0 :                 if (! script->mOutOfLine) {
    2814                 :                     rv |= script->Deserialize(aStream, aGlobal, aDocumentURI,
    2815               0 :                                               aNodeInfos);
    2816                 :                 } else {
    2817               0 :                     rv |= aStream->ReadObject(true, getter_AddRefs(script->mSrcURI));
    2818                 : 
    2819               0 :                     rv |= script->DeserializeOutOfLine(aStream, aGlobal);
    2820                 :                 }
    2821                 :                 // If we failed to deserialize, consider deleting 'script'?
    2822               0 :                 break;
    2823                 :             }
    2824                 :             default:
    2825               0 :                 NS_NOTREACHED("Unexpected child type!");
    2826               0 :                 rv = NS_ERROR_UNEXPECTED;
    2827                 :             }
    2828                 : 
    2829               0 :             mChildren.AppendElement(child);
    2830                 : 
    2831                 :             // Oh dear. Something failed during the deserialization.
    2832                 :             // We don't know what.  But likely consequences of failed
    2833                 :             // deserializations included calls to |AbortCaching| which
    2834                 :             // shuts down the cache and closes our streams.
    2835                 :             // If that happens, next time through this loop, we die a messy
    2836                 :             // death. So, let's just fail now, and propagate that failure
    2837                 :             // upward so that the ChromeProtocolHandler knows it can't use
    2838                 :             // a cached chrome channel for this.
    2839               0 :             if (NS_FAILED(rv))
    2840               0 :                 return rv;
    2841                 :         }
    2842                 :     }
    2843                 : 
    2844               0 :     return rv;
    2845                 : }
    2846                 : 
    2847                 : nsresult
    2848               0 : nsXULPrototypeElement::SetAttrAt(PRUint32 aPos, const nsAString& aValue,
    2849                 :                                  nsIURI* aDocumentURI)
    2850                 : {
    2851               0 :     NS_PRECONDITION(aPos < mNumAttributes, "out-of-bounds");
    2852                 : 
    2853                 :     // WARNING!!
    2854                 :     // This code is largely duplicated in nsXULElement::SetAttr.
    2855                 :     // Any changes should be made to both functions.
    2856                 : 
    2857               0 :     if (!mNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) {
    2858               0 :         mAttributes[aPos].mValue.ParseStringOrAtom(aValue);
    2859                 : 
    2860               0 :         return NS_OK;
    2861                 :     }
    2862                 : 
    2863               0 :     if (mAttributes[aPos].mName.Equals(nsGkAtoms::id) &&
    2864               0 :         !aValue.IsEmpty()) {
    2865               0 :         mHasIdAttribute = true;
    2866                 :         // Store id as atom.
    2867                 :         // id="" means that the element has no id. Not that it has
    2868                 :         // emptystring as id.
    2869               0 :         mAttributes[aPos].mValue.ParseAtom(aValue);
    2870                 : 
    2871               0 :         return NS_OK;
    2872                 :     }
    2873               0 :     else if (mAttributes[aPos].mName.Equals(nsGkAtoms::_class)) {
    2874               0 :         mHasClassAttribute = true;
    2875                 :         // Compute the element's class list
    2876               0 :         mAttributes[aPos].mValue.ParseAtomArray(aValue);
    2877                 : 
    2878               0 :         return NS_OK;
    2879                 :     }
    2880               0 :     else if (mAttributes[aPos].mName.Equals(nsGkAtoms::style)) {
    2881               0 :         mHasStyleAttribute = true;
    2882                 :         // Parse the element's 'style' attribute
    2883               0 :         nsRefPtr<css::StyleRule> rule;
    2884                 : 
    2885               0 :         nsCSSParser parser;
    2886                 : 
    2887                 :         // XXX Get correct Base URI (need GetBaseURI on *prototype* element)
    2888                 :         parser.ParseStyleAttribute(aValue, aDocumentURI, aDocumentURI,
    2889                 :                                    // This is basically duplicating what
    2890                 :                                    // nsINode::NodePrincipal() does
    2891                 :                                    mNodeInfo->NodeInfoManager()->
    2892                 :                                      DocumentPrincipal(),
    2893               0 :                                    getter_AddRefs(rule));
    2894               0 :         if (rule) {
    2895               0 :             mAttributes[aPos].mValue.SetTo(rule, &aValue);
    2896                 : 
    2897               0 :             return NS_OK;
    2898                 :         }
    2899                 :         // Don't abort if parsing failed, it could just be malformed css.
    2900                 :     }
    2901                 : 
    2902               0 :     mAttributes[aPos].mValue.ParseStringOrAtom(aValue);
    2903                 : 
    2904               0 :     return NS_OK;
    2905                 : }
    2906                 : 
    2907                 : void
    2908               0 : nsXULPrototypeElement::Unlink()
    2909                 : {
    2910               0 :     if (mHoldsScriptObject) {
    2911                 :         nsContentUtils::DropScriptObjects(mScriptTypeID, this,
    2912               0 :                                           &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode));
    2913               0 :         mHoldsScriptObject = false;
    2914                 :     }
    2915               0 :     mNumAttributes = 0;
    2916               0 :     delete[] mAttributes;
    2917               0 :     mAttributes = nsnull;
    2918               0 : }
    2919                 : 
    2920                 : //----------------------------------------------------------------------
    2921                 : //
    2922                 : // nsXULPrototypeScript
    2923                 : //
    2924                 : 
    2925               0 : nsXULPrototypeScript::nsXULPrototypeScript(PRUint32 aLangID, PRUint32 aLineNo, PRUint32 aVersion)
    2926                 :     : nsXULPrototypeNode(eType_Script),
    2927                 :       mLineNo(aLineNo),
    2928                 :       mSrcLoading(false),
    2929                 :       mOutOfLine(true),
    2930                 :       mSrcLoadWaiters(nsnull),
    2931                 :       mLangVersion(aVersion),
    2932               0 :       mScriptObject(aLangID)
    2933                 : {
    2934               0 :     NS_ASSERTION(aLangID != nsIProgrammingLanguage::UNKNOWN,
    2935                 :                  "The language ID must be known and constant");
    2936               0 : }
    2937                 : 
    2938                 : 
    2939               0 : nsXULPrototypeScript::~nsXULPrototypeScript()
    2940                 : {
    2941               0 :     UnlinkJSObjects();
    2942               0 : }
    2943                 : 
    2944                 : nsresult
    2945               0 : nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
    2946                 :                                 nsIScriptGlobalObject* aGlobal,
    2947                 :                                 const nsCOMArray<nsINodeInfo> *aNodeInfos)
    2948                 : {
    2949                 :     nsIScriptContext *context = aGlobal->GetScriptContext(
    2950               0 :                                         mScriptObject.mLangID);
    2951               0 :     NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nsnull ||
    2952                 :                  !mScriptObject.mObject,
    2953                 :                  "script source still loading when serializing?!");
    2954               0 :     if (!mScriptObject.mObject)
    2955               0 :         return NS_ERROR_FAILURE;
    2956                 : 
    2957                 :     // Write basic prototype data
    2958                 :     nsresult rv;
    2959               0 :     rv = aStream->Write32(mLineNo);
    2960               0 :     if (NS_FAILED(rv)) return rv;
    2961               0 :     rv = aStream->Write32(mLangVersion);
    2962               0 :     if (NS_FAILED(rv)) return rv;
    2963                 :     // And delegate the writing to the nsIScriptContext
    2964               0 :     rv = context->Serialize(aStream, mScriptObject.mObject);
    2965               0 :     if (NS_FAILED(rv)) return rv;
    2966                 : 
    2967               0 :     return NS_OK;
    2968                 : }
    2969                 : 
    2970                 : nsresult
    2971               0 : nsXULPrototypeScript::SerializeOutOfLine(nsIObjectOutputStream* aStream,
    2972                 :                                          nsIScriptGlobalObject* aGlobal)
    2973                 : {
    2974               0 :     nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
    2975                 : 
    2976               0 :     bool isChrome = false;
    2977               0 :     if (NS_FAILED(mSrcURI->SchemeIs("chrome", &isChrome)) || !isChrome)
    2978                 :        // Don't cache scripts that don't come from chrome uris.
    2979               0 :        return rv;
    2980                 : 
    2981               0 :     nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
    2982               0 :     if (!cache)
    2983               0 :         return NS_ERROR_OUT_OF_MEMORY;
    2984                 : 
    2985               0 :     NS_ASSERTION(cache->IsEnabled(),
    2986                 :                  "writing to the cache file, but the XUL cache is off?");
    2987                 :     bool exists;
    2988               0 :     cache->HasData(mSrcURI, &exists);
    2989                 :     
    2990                 :     
    2991                 :     /* return will be NS_OK from GetAsciiSpec.
    2992                 :      * that makes no sense.
    2993                 :      * nor does returning NS_OK from HasMuxedDocument.
    2994                 :      * XXX return something meaningful.
    2995                 :      */
    2996               0 :     if (exists)
    2997               0 :         return NS_OK;
    2998                 : 
    2999               0 :     nsCOMPtr<nsIObjectOutputStream> oos;
    3000               0 :     rv = cache->GetOutputStream(mSrcURI, getter_AddRefs(oos));
    3001               0 :     NS_ENSURE_SUCCESS(rv, rv);
    3002                 :     
    3003               0 :     rv |= Serialize(oos, aGlobal, nsnull);
    3004               0 :     rv |= cache->FinishOutputStream(mSrcURI);
    3005                 : 
    3006               0 :     if (NS_FAILED(rv))
    3007               0 :         cache->AbortCaching();
    3008               0 :     return rv;
    3009                 : }
    3010                 : 
    3011                 : 
    3012                 : nsresult
    3013               0 : nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream,
    3014                 :                                   nsIScriptGlobalObject* aGlobal,
    3015                 :                                   nsIURI* aDocumentURI,
    3016                 :                                   const nsCOMArray<nsINodeInfo> *aNodeInfos)
    3017                 : {
    3018                 :     nsresult rv;
    3019                 : 
    3020               0 :     NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nsnull ||
    3021                 :                  !mScriptObject.mObject,
    3022                 :                  "prototype script not well-initialized when deserializing?!");
    3023                 : 
    3024                 :     // Read basic prototype data
    3025               0 :     aStream->Read32(&mLineNo);
    3026               0 :     aStream->Read32(&mLangVersion);
    3027                 : 
    3028                 :     nsIScriptContext *context = aGlobal->GetScriptContext(
    3029               0 :                                             mScriptObject.mLangID);
    3030               0 :     NS_ASSERTION(context != nsnull, "Have no context for deserialization");
    3031               0 :     NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED);
    3032               0 :     nsScriptObjectHolder<JSScript> newScriptObject(context);
    3033               0 :     rv = context->Deserialize(aStream, newScriptObject);
    3034               0 :     if (NS_FAILED(rv)) {
    3035               0 :         NS_WARNING("Language deseralization failed");
    3036               0 :         return rv;
    3037                 :     }
    3038               0 :     Set(newScriptObject);
    3039               0 :     return NS_OK;
    3040                 : }
    3041                 : 
    3042                 : 
    3043                 : nsresult
    3044               0 : nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput,
    3045                 :                                            nsIScriptGlobalObject* aGlobal)
    3046                 : {
    3047                 :     // Keep track of failure via rv, so we can
    3048                 :     // AbortCaching if things look bad.
    3049               0 :     nsresult rv = NS_OK;
    3050               0 :     nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
    3051                 :   
    3052               0 :     nsCOMPtr<nsIObjectInputStream> objectInput = aInput;
    3053               0 :     if (cache) {
    3054               0 :         bool useXULCache = true;
    3055               0 :         if (mSrcURI) {
    3056                 :             // NB: we must check the XUL script cache early, to avoid
    3057                 :             // multiple deserialization attempts for a given script.            
    3058                 :             // Note that nsXULDocument::LoadScript
    3059                 :             // checks the XUL script cache too, in order to handle the
    3060                 :             // serialization case.
    3061                 :             //
    3062                 :             // We need do this only for <script src='strres.js'> and the
    3063                 :             // like, i.e., out-of-line scripts that are included by several
    3064                 :             // different XUL documents stored in the cache file.
    3065               0 :             useXULCache = cache->IsEnabled();
    3066                 : 
    3067               0 :             if (useXULCache) {
    3068               0 :                 PRUint32 newLangID = nsIProgrammingLanguage::UNKNOWN;
    3069                 :                 JSScript* newScriptObject =
    3070               0 :                     cache->GetScript(mSrcURI, &newLangID);
    3071               0 :                 if (newScriptObject) {
    3072                 :                     // Things may blow here if we simply change the script
    3073                 :                     // language - other code may already have pre-fetched the
    3074                 :                     // global for the language. (You can see this code by
    3075                 :                     // setting langID to UNKNOWN in the nsXULPrototypeScript
    3076                 :                     // ctor and not setting it until the scriptObject is set -
    3077                 :                     // code that pre-fetches these globals will then start
    3078                 :                     // asserting.)
    3079               0 :                     if (mScriptObject.mLangID != newLangID) {
    3080               0 :                         NS_ERROR("XUL cache gave different language?");
    3081               0 :                         return NS_ERROR_UNEXPECTED;
    3082                 :                     }
    3083               0 :                     Set(newScriptObject);
    3084                 :                 }
    3085                 :             }
    3086                 :         }
    3087                 : 
    3088               0 :         if (! mScriptObject.mObject) {
    3089               0 :             if (mSrcURI) {
    3090               0 :                 rv = cache->GetInputStream(mSrcURI, getter_AddRefs(objectInput));
    3091                 :             } 
    3092                 :             // If !mSrcURI, we have an inline script. We shouldn't have 
    3093                 :             // to do anything else in that case, I think.
    3094                 :  
    3095                 :             // We do reflect errors into rv, but our caller may want to
    3096                 :             // ignore our return value, because mScriptObject will be null
    3097                 :             // after any error, and that suffices to cause the script to
    3098                 :             // be reloaded (from the src= URI, if any) and recompiled.
    3099                 :             // We're better off slow-loading than bailing out due to a
    3100                 :             // error.
    3101               0 :             if (NS_SUCCEEDED(rv))
    3102               0 :                 rv = Deserialize(objectInput, aGlobal, nsnull, nsnull);
    3103                 : 
    3104               0 :             if (NS_SUCCEEDED(rv)) {
    3105               0 :                 if (useXULCache && mSrcURI) {
    3106               0 :                     bool isChrome = false;
    3107               0 :                     mSrcURI->SchemeIs("chrome", &isChrome);
    3108               0 :                     if (isChrome) {
    3109                 :                         cache->PutScript(mSrcURI,
    3110                 :                                          mScriptObject.mLangID,
    3111               0 :                                          mScriptObject.mObject);
    3112                 :                     }
    3113                 :                 }
    3114               0 :                 cache->FinishInputStream(mSrcURI);
    3115                 :             } else {
    3116                 :                 // If mSrcURI is not in the cache,
    3117                 :                 // rv will be NS_ERROR_NOT_AVAILABLE and we'll try to
    3118                 :                 // update the cache file to hold a serialization of
    3119                 :                 // this script, once it has finished loading.
    3120               0 :                 if (rv != NS_ERROR_NOT_AVAILABLE)
    3121               0 :                     cache->AbortCaching();
    3122                 :             }
    3123                 :         }
    3124                 :     }
    3125               0 :     return rv;
    3126                 : }
    3127                 : 
    3128                 : nsresult
    3129               0 : nsXULPrototypeScript::Compile(const PRUnichar* aText,
    3130                 :                               PRInt32 aTextLength,
    3131                 :                               nsIURI* aURI,
    3132                 :                               PRUint32 aLineNo,
    3133                 :                               nsIDocument* aDocument,
    3134                 :                               nsIScriptGlobalObjectOwner* aGlobalOwner)
    3135                 : {
    3136                 :     // We'll compile the script using the prototype document's special
    3137                 :     // script object as the parent. This ensures that we won't end up
    3138                 :     // with an uncollectable reference.
    3139                 :     //
    3140                 :     // Compiling it using (for example) the first document's global
    3141                 :     // object would cause JS to keep a reference via the __proto__ or
    3142                 :     // parent pointer to the first document's global. If that happened,
    3143                 :     // our script object would reference the first document, and the
    3144                 :     // first document would indirectly reference the prototype document
    3145                 :     // because it keeps the prototype cache alive. Circularity!
    3146                 :     nsresult rv;
    3147                 : 
    3148                 :     // Use the prototype document's special context
    3149                 :     nsIScriptContext *context;
    3150                 : 
    3151                 :     {
    3152               0 :         nsIScriptGlobalObject* global = aGlobalOwner->GetScriptGlobalObject();
    3153               0 :         NS_ASSERTION(global != nsnull, "prototype doc has no script global");
    3154               0 :         if (! global)
    3155               0 :             return NS_ERROR_UNEXPECTED;
    3156                 : 
    3157               0 :         context = global->GetScriptContext(mScriptObject.mLangID);
    3158               0 :         NS_ASSERTION(context != nsnull, "no context for script global");
    3159               0 :         if (! context)
    3160               0 :             return NS_ERROR_UNEXPECTED;
    3161                 :     }
    3162                 : 
    3163               0 :     nsCAutoString urlspec;
    3164               0 :     nsContentUtils::GetWrapperSafeScriptFilename(aDocument, aURI, urlspec);
    3165                 : 
    3166                 :     // Ok, compile it to create a prototype script object!
    3167                 : 
    3168               0 :     nsScriptObjectHolder<JSScript> newScriptObject(context);
    3169                 :     rv = context->CompileScript(aText,
    3170                 :                                 aTextLength,
    3171                 :                                 // Use the enclosing document's principal
    3172                 :                                 // XXX is this right? or should we use the
    3173                 :                                 // protodoc's?
    3174                 :                                 // If we start using the protodoc's, make sure
    3175                 :                                 // the DowngradePrincipalIfNeeded stuff in
    3176                 :                                 // nsXULDocument::OnStreamComplete still works!
    3177                 :                                 aDocument->NodePrincipal(),
    3178                 :                                 urlspec.get(),
    3179                 :                                 aLineNo,
    3180                 :                                 mLangVersion,
    3181               0 :                                 newScriptObject);
    3182               0 :     if (NS_FAILED(rv))
    3183               0 :         return rv;
    3184                 : 
    3185               0 :     Set(newScriptObject);
    3186               0 :     return rv;
    3187                 : }
    3188                 : 
    3189                 : void
    3190               0 : nsXULPrototypeScript::UnlinkJSObjects()
    3191                 : {
    3192               0 :     if (mScriptObject.mObject) {
    3193                 :         nsContentUtils::DropScriptObjects(mScriptObject.mLangID, this,
    3194               0 :                                           &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode));
    3195               0 :         mScriptObject.mObject = nsnull;
    3196                 :     }
    3197               0 : }
    3198                 : 
    3199                 : void
    3200               0 : nsXULPrototypeScript::Set(JSScript* aObject)
    3201                 : {
    3202               0 :     NS_ASSERTION(!mScriptObject.mObject, "Leaking script object.");
    3203               0 :     if (!aObject) {
    3204               0 :         mScriptObject.mObject = nsnull;
    3205                 : 
    3206               0 :         return;
    3207                 :     }
    3208                 : 
    3209                 :     nsresult rv = nsContentUtils::HoldScriptObject(mScriptObject.mLangID,
    3210                 :                                                    this,
    3211                 :                                                    &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode),
    3212               0 :                                                    aObject, false);
    3213               0 :     if (NS_SUCCEEDED(rv)) {
    3214               0 :         mScriptObject.mObject = aObject;
    3215                 :     }
    3216                 : }
    3217                 : 
    3218                 : //----------------------------------------------------------------------
    3219                 : //
    3220                 : // nsXULPrototypeText
    3221                 : //
    3222                 : 
    3223                 : nsresult
    3224               0 : nsXULPrototypeText::Serialize(nsIObjectOutputStream* aStream,
    3225                 :                               nsIScriptGlobalObject* aGlobal,
    3226                 :                               const nsCOMArray<nsINodeInfo> *aNodeInfos)
    3227                 : {
    3228                 :     nsresult rv;
    3229                 : 
    3230                 :     // Write basic prototype data
    3231               0 :     rv = aStream->Write32(mType);
    3232                 : 
    3233               0 :     rv |= aStream->WriteWStringZ(mValue.get());
    3234                 : 
    3235               0 :     return rv;
    3236                 : }
    3237                 : 
    3238                 : nsresult
    3239               0 : nsXULPrototypeText::Deserialize(nsIObjectInputStream* aStream,
    3240                 :                                 nsIScriptGlobalObject* aGlobal,
    3241                 :                                 nsIURI* aDocumentURI,
    3242                 :                                 const nsCOMArray<nsINodeInfo> *aNodeInfos)
    3243                 : {
    3244                 :     nsresult rv;
    3245                 : 
    3246               0 :     rv = aStream->ReadString(mValue);
    3247                 : 
    3248               0 :     return rv;
    3249                 : }
    3250                 : 
    3251                 : //----------------------------------------------------------------------
    3252                 : //
    3253                 : // nsXULPrototypePI
    3254                 : //
    3255                 : 
    3256                 : nsresult
    3257               0 : nsXULPrototypePI::Serialize(nsIObjectOutputStream* aStream,
    3258                 :                             nsIScriptGlobalObject* aGlobal,
    3259                 :                             const nsCOMArray<nsINodeInfo> *aNodeInfos)
    3260                 : {
    3261                 :     nsresult rv;
    3262                 : 
    3263                 :     // Write basic prototype data
    3264               0 :     rv = aStream->Write32(mType);
    3265                 : 
    3266               0 :     rv |= aStream->WriteWStringZ(mTarget.get());
    3267               0 :     rv |= aStream->WriteWStringZ(mData.get());
    3268                 : 
    3269               0 :     return rv;
    3270                 : }
    3271                 : 
    3272                 : nsresult
    3273               0 : nsXULPrototypePI::Deserialize(nsIObjectInputStream* aStream,
    3274                 :                               nsIScriptGlobalObject* aGlobal,
    3275                 :                               nsIURI* aDocumentURI,
    3276                 :                               const nsCOMArray<nsINodeInfo> *aNodeInfos)
    3277                 : {
    3278                 :     nsresult rv;
    3279                 : 
    3280               0 :     rv = aStream->ReadString(mTarget);
    3281               0 :     rv |= aStream->ReadString(mData);
    3282                 : 
    3283               0 :     return rv;
    3284            4392 : }

Generated by: LCOV version 1.7