LCOV - code coverage report
Current view: directory - content/xul/content/src - nsXULElement.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1367 167 12.2 %
Date: 2012-04-21 Functions: 207 38 18.4 %

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

Generated by: LCOV version 1.7