LCOV - code coverage report
Current view: top level - dom/xul - nsXULElement.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 593 1320 44.9 %
Date: 2017-07-14 16:53:18 Functions: 73 147 49.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * This Original Code has been modified by IBM Corporation.
       7             :  * Modifications made by IBM described herein are
       8             :  * Copyright (c) International Business Machines
       9             :  * Corporation, 2000
      10             :  *
      11             :  * Modifications to Mozilla code or documentation
      12             :  * identified per MPL Section 3.3
      13             :  *
      14             :  * Date         Modified by     Description of modification
      15             :  * 03/27/2000   IBM Corp.       Added PR_CALLBACK for Optlink
      16             :  *                               use in OS2
      17             :  */
      18             : 
      19             : #include "nsCOMPtr.h"
      20             : #include "nsDOMCID.h"
      21             : #include "nsError.h"
      22             : #include "nsDOMString.h"
      23             : #include "nsIDOMEvent.h"
      24             : #include "nsIAtom.h"
      25             : #include "nsIBaseWindow.h"
      26             : #include "nsIDOMAttr.h"
      27             : #include "nsIDOMDocument.h"
      28             : #include "nsIDOMElement.h"
      29             : #include "nsIDOMEventListener.h"
      30             : #include "nsIDOMNodeList.h"
      31             : #include "nsIDOMXULCommandDispatcher.h"
      32             : #include "nsIDOMXULElement.h"
      33             : #include "nsIDOMXULSelectCntrlItemEl.h"
      34             : #include "nsIDocument.h"
      35             : #include "nsLayoutStylesheetCache.h"
      36             : #include "mozilla/AsyncEventDispatcher.h"
      37             : #include "mozilla/ClearOnShutdown.h"
      38             : #include "mozilla/EventListenerManager.h"
      39             : #include "mozilla/EventStateManager.h"
      40             : #include "mozilla/EventStates.h"
      41             : #include "mozilla/DeclarationBlockInlines.h"
      42             : #include "nsFocusManager.h"
      43             : #include "nsHTMLStyleSheet.h"
      44             : #include "nsNameSpaceManager.h"
      45             : #include "nsIObjectInputStream.h"
      46             : #include "nsIObjectOutputStream.h"
      47             : #include "nsIPresShell.h"
      48             : #include "nsIPrincipal.h"
      49             : #include "nsIRDFCompositeDataSource.h"
      50             : #include "nsIRDFNode.h"
      51             : #include "nsIRDFService.h"
      52             : #include "nsIScriptContext.h"
      53             : #include "nsIScriptError.h"
      54             : #include "nsIScriptSecurityManager.h"
      55             : #include "nsIServiceManager.h"
      56             : #include "mozilla/css/StyleRule.h"
      57             : #include "nsIURL.h"
      58             : #include "nsViewManager.h"
      59             : #include "nsIWidget.h"
      60             : #include "nsIXULDocument.h"
      61             : #include "nsIXULTemplateBuilder.h"
      62             : #include "nsLayoutCID.h"
      63             : #include "nsContentCID.h"
      64             : #include "mozilla/dom/Event.h"
      65             : #include "nsRDFCID.h"
      66             : #include "nsStyleConsts.h"
      67             : #include "nsXPIDLString.h"
      68             : #include "nsXULControllers.h"
      69             : #include "nsIBoxObject.h"
      70             : #include "nsPIBoxObject.h"
      71             : #include "XULDocument.h"
      72             : #include "nsXULPopupListener.h"
      73             : #include "nsRuleWalker.h"
      74             : #include "nsIDOMCSSStyleDeclaration.h"
      75             : #include "nsCSSParser.h"
      76             : #include "ListBoxObject.h"
      77             : #include "nsContentUtils.h"
      78             : #include "nsContentList.h"
      79             : #include "mozilla/InternalMutationEvent.h"
      80             : #include "mozilla/MouseEvents.h"
      81             : #include "nsIDOMMutationEvent.h"
      82             : #include "nsPIDOMWindow.h"
      83             : #include "nsJSPrincipals.h"
      84             : #include "nsDOMAttributeMap.h"
      85             : #include "nsGkAtoms.h"
      86             : #include "nsXULContentUtils.h"
      87             : #include "nsNodeUtils.h"
      88             : #include "nsFrameLoader.h"
      89             : #include "mozilla/Logging.h"
      90             : #include "rdf.h"
      91             : #include "nsIControllers.h"
      92             : #include "nsAttrValueOrString.h"
      93             : #include "nsAttrValueInlines.h"
      94             : #include "mozilla/Attributes.h"
      95             : #include "nsIController.h"
      96             : #include "nsQueryObject.h"
      97             : #include <algorithm>
      98             : #include "nsIDOMChromeWindow.h"
      99             : 
     100             : // The XUL doc interface
     101             : #include "nsIDOMXULDocument.h"
     102             : 
     103             : #include "nsReadableUtils.h"
     104             : #include "nsIFrame.h"
     105             : #include "nsNodeInfoManager.h"
     106             : #include "nsXBLBinding.h"
     107             : #include "mozilla/EventDispatcher.h"
     108             : #include "mozAutoDocUpdate.h"
     109             : #include "nsIDOMXULCommandEvent.h"
     110             : #include "nsCCUncollectableMarker.h"
     111             : #include "nsICSSDeclaration.h"
     112             : 
     113             : #include "mozilla/dom/XULElementBinding.h"
     114             : #include "mozilla/dom/BoxObject.h"
     115             : #include "mozilla/dom/HTMLIFrameElement.h"
     116             : 
     117             : using namespace mozilla;
     118             : using namespace mozilla::dom;
     119             : 
     120             : #ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
     121             : uint32_t             nsXULPrototypeAttribute::gNumElements;
     122             : uint32_t             nsXULPrototypeAttribute::gNumAttributes;
     123             : uint32_t             nsXULPrototypeAttribute::gNumCacheTests;
     124             : uint32_t             nsXULPrototypeAttribute::gNumCacheHits;
     125             : uint32_t             nsXULPrototypeAttribute::gNumCacheSets;
     126             : uint32_t             nsXULPrototypeAttribute::gNumCacheFills;
     127             : #endif
     128             : 
     129             : #define NS_DISPATCH_XUL_COMMAND     (1 << 0)
     130             : 
     131             : class nsXULElementTearoff final : public nsIFrameLoaderOwner
     132             : {
     133         142 :   ~nsXULElementTearoff() {}
     134             : 
     135             : public:
     136             :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     137        1423 :   NS_DECL_CYCLE_COLLECTION_CLASS(nsXULElementTearoff)
     138             : 
     139         143 :   explicit nsXULElementTearoff(nsXULElement* aElement)
     140         143 :     : mElement(aElement)
     141             :   {
     142         143 :   }
     143             : 
     144          92 :   NS_FORWARD_NSIFRAMELOADEROWNER(static_cast<nsXULElement*>(mElement.get())->)
     145             : private:
     146             :   nsCOMPtr<nsIDOMXULElement> mElement;
     147             : };
     148             : 
     149           0 : NS_IMPL_CYCLE_COLLECTION(nsXULElementTearoff, mElement)
     150             : 
     151         143 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULElementTearoff)
     152         427 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULElementTearoff)
     153             : 
     154         711 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULElementTearoff)
     155           0 :   NS_INTERFACE_MAP_ENTRY(nsIFrameLoaderOwner)
     156           0 : NS_INTERFACE_MAP_END_AGGREGATED(mElement)
     157             : 
     158             : //----------------------------------------------------------------------
     159             : // nsXULElement
     160             : //
     161             : 
     162        2273 : nsXULElement::nsXULElement(already_AddRefed<mozilla::dom::NodeInfo> aNodeInfo)
     163             :     : nsStyledElement(aNodeInfo),
     164        2273 :       mBindingParent(nullptr)
     165             : {
     166             :     XUL_PROTOTYPE_ATTRIBUTE_METER(gNumElements);
     167             : 
     168             :     // We may be READWRITE by default; check.
     169        2273 :     if (IsReadWriteTextElement()) {
     170           5 :         AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
     171           5 :         RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
     172             :     }
     173        2273 : }
     174             : 
     175          62 : nsXULElement::~nsXULElement()
     176             : {
     177          93 : }
     178             : 
     179         706 : nsXULElement::nsXULSlots::nsXULSlots()
     180         706 :     : nsXULElement::nsDOMSlots()
     181             : {
     182         706 : }
     183             : 
     184           0 : nsXULElement::nsXULSlots::~nsXULSlots()
     185             : {
     186           0 :     NS_IF_RELEASE(mControllers); // Forces release
     187           0 :     nsCOMPtr<nsIFrameLoader> frameLoader = do_QueryInterface(mFrameLoaderOrOpener);
     188           0 :     if (frameLoader) {
     189           0 :         static_cast<nsFrameLoader*>(frameLoader.get())->Destroy();
     190             :     }
     191           0 : }
     192             : 
     193             : void
     194         287 : nsXULElement::nsXULSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
     195             : {
     196         287 :     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mFrameLoaderOrOpener");
     197         287 :     cb.NoteXPCOMChild(mFrameLoaderOrOpener);
     198         287 : }
     199             : 
     200             : nsINode::nsSlots*
     201         706 : nsXULElement::CreateSlots()
     202             : {
     203         706 :     return new nsXULSlots();
     204             : }
     205             : 
     206             : void
     207           1 : nsXULElement::MaybeUpdatePrivateLifetime()
     208             : {
     209           2 :     if (AttrValueIs(kNameSpaceID_None, nsGkAtoms::windowtype,
     210           2 :                     NS_LITERAL_STRING("navigator:browser"),
     211           1 :                     eCaseMatters)) {
     212           1 :         return;
     213             :     }
     214             : 
     215           0 :     nsPIDOMWindowOuter* win = OwnerDoc()->GetWindow();
     216           0 :     nsCOMPtr<nsIDocShell> docShell = win ? win->GetDocShell() : nullptr;
     217           0 :     if (docShell) {
     218           0 :         docShell->SetAffectPrivateSessionLifetime(false);
     219             :     }
     220             : }
     221             : 
     222             : /* static */
     223             : already_AddRefed<nsXULElement>
     224        1667 : nsXULElement::Create(nsXULPrototypeElement* aPrototype, mozilla::dom::NodeInfo *aNodeInfo,
     225             :                      bool aIsScriptable, bool aIsRoot)
     226             : {
     227        3334 :     RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
     228        5001 :     RefPtr<nsXULElement> element = new nsXULElement(ni.forget());
     229        1667 :     if (element) {
     230        1667 :         if (aPrototype->mHasIdAttribute) {
     231         979 :             element->SetHasID();
     232             :         }
     233        1667 :         if (aPrototype->mHasClassAttribute) {
     234         605 :             element->SetMayHaveClass();
     235             :         }
     236        1667 :         if (aPrototype->mHasStyleAttribute) {
     237           7 :             element->SetMayHaveStyle();
     238             :         }
     239             : 
     240        1667 :         element->MakeHeavyweight(aPrototype);
     241        1667 :         if (aIsScriptable) {
     242             :             // Check each attribute on the prototype to see if we need to do
     243             :             // any additional processing and hookup that would otherwise be
     244             :             // done 'automagically' by SetAttr().
     245        5162 :             for (uint32_t i = 0; i < aPrototype->mNumAttributes; ++i) {
     246        3894 :                 element->AddListenerFor(aPrototype->mAttributes[i].mName,
     247        3894 :                                         true);
     248             :             }
     249             :         }
     250             : 
     251        1667 :         if (aIsRoot && aPrototype->mNodeInfo->Equals(nsGkAtoms::window)) {
     252          26 :             for (uint32_t i = 0; i < aPrototype->mNumAttributes; ++i) {
     253          25 :                 if (aPrototype->mAttributes[i].mName.Equals(nsGkAtoms::windowtype)) {
     254           1 :                     element->MaybeUpdatePrivateLifetime();
     255             :                 }
     256             :             }
     257             :         }
     258             :     }
     259             : 
     260        3334 :     return element.forget();
     261             : }
     262             : 
     263             : nsresult
     264        1667 : nsXULElement::Create(nsXULPrototypeElement* aPrototype,
     265             :                      nsIDocument* aDocument,
     266             :                      bool aIsScriptable,
     267             :                      bool aIsRoot,
     268             :                      Element** aResult)
     269             : {
     270             :     // Create an nsXULElement from a prototype
     271        1667 :     NS_PRECONDITION(aPrototype != nullptr, "null ptr");
     272        1667 :     if (! aPrototype)
     273           0 :         return NS_ERROR_NULL_POINTER;
     274             : 
     275        1667 :     NS_PRECONDITION(aResult != nullptr, "null ptr");
     276        1667 :     if (! aResult)
     277           0 :         return NS_ERROR_NULL_POINTER;
     278             : 
     279        3334 :     RefPtr<mozilla::dom::NodeInfo> nodeInfo;
     280        1667 :     if (aDocument) {
     281        1667 :         mozilla::dom::NodeInfo* ni = aPrototype->mNodeInfo;
     282             :         nodeInfo = aDocument->NodeInfoManager()->
     283        3334 :           GetNodeInfo(ni->NameAtom(), ni->GetPrefixAtom(), ni->NamespaceID(),
     284        1667 :                       nsIDOMNode::ELEMENT_NODE);
     285             :     } else {
     286           0 :         nodeInfo = aPrototype->mNodeInfo;
     287             :     }
     288             : 
     289        3334 :     RefPtr<nsXULElement> element = Create(aPrototype, nodeInfo,
     290        3334 :                                             aIsScriptable, aIsRoot);
     291        1667 :     element.forget(aResult);
     292             : 
     293        1667 :     return NS_OK;
     294             : }
     295             : 
     296             : nsresult
     297          58 : NS_NewXULElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
     298             : {
     299         116 :     RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
     300             : 
     301          58 :     NS_PRECONDITION(ni, "need nodeinfo for non-proto Create");
     302             : 
     303          58 :     nsIDocument* doc = ni->GetDocument();
     304          58 :     if (doc && !doc->AllowXULXBL()) {
     305           0 :         return NS_ERROR_NOT_AVAILABLE;
     306             :     }
     307             : 
     308         116 :     NS_ADDREF(*aResult = new nsXULElement(ni.forget()));
     309             : 
     310          58 :     return NS_OK;
     311             : }
     312             : 
     313             : void
     314           6 : NS_TrustedNewXULElement(nsIContent** aResult,
     315             :                         already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
     316             : {
     317          12 :     RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
     318           6 :     NS_PRECONDITION(ni, "need nodeinfo for non-proto Create");
     319             : 
     320             :     // Create an nsXULElement with the specified namespace and tag.
     321          12 :     NS_ADDREF(*aResult = new nsXULElement(ni.forget()));
     322           6 : }
     323             : 
     324             : //----------------------------------------------------------------------
     325             : // nsISupports interface
     326             : 
     327             : NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULElement)
     328             : 
     329         424 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULElement,
     330             :                                                   nsStyledElement)
     331             :     {
     332         424 :         nsXULSlots* slots = static_cast<nsXULSlots*>(tmp->GetExistingSlots());
     333         424 :         if (slots) {
     334         287 :             slots->Traverse(cb);
     335             :         }
     336             :     }
     337         424 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     338             : 
     339           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULElement,
     340             :                                                 nsStyledElement)
     341             :     // Why aren't we unlinking the prototype?
     342           0 :     tmp->ClearHasID();
     343           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     344             : 
     345       30103 : NS_IMPL_ADDREF_INHERITED(nsXULElement, nsStyledElement)
     346       23794 : NS_IMPL_RELEASE_INHERITED(nsXULElement, nsStyledElement)
     347             : 
     348       20383 : NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXULElement)
     349       15653 :     NS_INTERFACE_TABLE_INHERITED(nsXULElement, nsIDOMNode, nsIDOMElement,
     350             :                                  nsIDOMXULElement)
     351       15653 :     NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE
     352         447 :     NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIFrameLoaderOwner,
     353             :                                    new nsXULElementTearoff(this))
     354         161 : NS_INTERFACE_MAP_END_INHERITING(nsStyledElement)
     355             : 
     356             : //----------------------------------------------------------------------
     357             : // nsIDOMNode interface
     358             : 
     359             : nsresult
     360         542 : nsXULElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
     361             :                     bool aPreallocateChildren) const
     362             : {
     363         542 :     *aResult = nullptr;
     364             : 
     365        1084 :     RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
     366        1626 :     RefPtr<nsXULElement> element = new nsXULElement(ni.forget());
     367             : 
     368         542 :     nsresult rv = element->mAttrsAndChildren.EnsureCapacityToClone(mAttrsAndChildren,
     369         542 :                                                                    aPreallocateChildren);
     370         542 :     NS_ENSURE_SUCCESS(rv, rv);
     371             : 
     372             :     // XXX TODO: set up RDF generic builder n' stuff if there is a
     373             :     // 'datasources' attribute? This is really kind of tricky,
     374             :     // because then we'd need to -selectively- copy children that
     375             :     // -weren't- generated from RDF. Ugh. Forget it.
     376             : 
     377             :     // Note that we're _not_ copying mControllers.
     378             : 
     379         542 :     uint32_t count = mAttrsAndChildren.AttrCount();
     380         542 :     rv = NS_OK;
     381        2085 :     for (uint32_t i = 0; i < count; ++i) {
     382        1543 :         const nsAttrName* originalName = mAttrsAndChildren.AttrNameAt(i);
     383        1543 :         const nsAttrValue* originalValue = mAttrsAndChildren.AttrAt(i);
     384        3086 :         nsAttrValue attrValue;
     385             : 
     386             :         // Style rules need to be cloned.
     387        1543 :         if (originalValue->Type() == nsAttrValue::eCSSDeclaration) {
     388           3 :             DeclarationBlock* decl = originalValue->GetCSSDeclarationValue();
     389           6 :             RefPtr<DeclarationBlock> declClone = decl->Clone();
     390             : 
     391           6 :             nsString stringValue;
     392           3 :             originalValue->ToString(stringValue);
     393             : 
     394           3 :             attrValue.SetTo(declClone.forget(), &stringValue);
     395             :         } else {
     396        1540 :             attrValue.SetTo(*originalValue);
     397             :         }
     398             : 
     399             :         bool oldValueSet;
     400        1543 :         if (originalName->IsAtom()) {
     401        1187 :            rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->Atom(),
     402             :                                                           attrValue,
     403        1187 :                                                           &oldValueSet);
     404             :         } else {
     405         356 :             rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->NodeInfo(),
     406             :                                                            attrValue,
     407         356 :                                                            &oldValueSet);
     408             :         }
     409        1543 :         NS_ENSURE_SUCCESS(rv, rv);
     410        1543 :         element->AddListenerFor(*originalName, true);
     411        1549 :         if (originalName->Equals(nsGkAtoms::id) &&
     412           6 :             !originalValue->IsEmptyString()) {
     413           6 :             element->SetHasID();
     414             :         }
     415        1543 :         if (originalName->Equals(nsGkAtoms::_class)) {
     416         439 :             element->SetMayHaveClass();
     417             :         }
     418        1543 :         if (originalName->Equals(nsGkAtoms::style)) {
     419           3 :             element->SetMayHaveStyle();
     420             :         }
     421             :     }
     422             : 
     423         542 :     element.forget(aResult);
     424         542 :     return rv;
     425             : }
     426             : 
     427             : //----------------------------------------------------------------------
     428             : 
     429             : already_AddRefed<nsINodeList>
     430           2 : nsXULElement::GetElementsByAttribute(const nsAString& aAttribute,
     431             :                                      const nsAString& aValue)
     432             : {
     433           4 :     nsCOMPtr<nsIAtom> attrAtom(NS_Atomize(aAttribute));
     434           2 :     void* attrValue = new nsString(aValue);
     435             :     RefPtr<nsContentList> list =
     436             :         new nsContentList(this,
     437             :                           XULDocument::MatchAttribute,
     438             :                           nsContentUtils::DestroyMatchString,
     439             :                           attrValue,
     440             :                           true,
     441             :                           attrAtom,
     442           6 :                           kNameSpaceID_Unknown);
     443           4 :     return list.forget();
     444             : }
     445             : 
     446             : already_AddRefed<nsINodeList>
     447           0 : nsXULElement::GetElementsByAttributeNS(const nsAString& aNamespaceURI,
     448             :                                        const nsAString& aAttribute,
     449             :                                        const nsAString& aValue,
     450             :                                        ErrorResult& rv)
     451             : {
     452           0 :     nsCOMPtr<nsIAtom> attrAtom(NS_Atomize(aAttribute));
     453             : 
     454           0 :     int32_t nameSpaceId = kNameSpaceID_Wildcard;
     455           0 :     if (!aNamespaceURI.EqualsLiteral("*")) {
     456           0 :       rv =
     457             :         nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
     458           0 :                                                               nameSpaceId);
     459           0 :       if (rv.Failed()) {
     460           0 :           return nullptr;
     461             :       }
     462             :     }
     463             : 
     464           0 :     void* attrValue = new nsString(aValue);
     465             :     RefPtr<nsContentList> list =
     466             :         new nsContentList(this,
     467             :                           XULDocument::MatchAttribute,
     468             :                           nsContentUtils::DestroyMatchString,
     469             :                           attrValue,
     470             :                           true,
     471             :                           attrAtom,
     472           0 :                           nameSpaceId);
     473             : 
     474           0 :     return list.forget();
     475             : }
     476             : 
     477             : EventListenerManager*
     478         553 : nsXULElement::GetEventListenerManagerForAttr(nsIAtom* aAttrName, bool* aDefer)
     479             : {
     480             :     // XXXbz sXBL/XBL2 issue: should we instead use GetComposedDoc()
     481             :     // here, override BindToTree for those classes and munge event
     482             :     // listeners there?
     483         553 :     nsIDocument* doc = OwnerDoc();
     484             : 
     485             :     nsPIDOMWindowInner *window;
     486         553 :     Element *root = doc->GetRootElement();
     487         553 :     if ((!root || root == this) && !mNodeInfo->Equals(nsGkAtoms::overlay) &&
     488             :         (window = doc->GetInnerWindow())) {
     489             : 
     490           6 :         nsCOMPtr<EventTarget> piTarget = do_QueryInterface(window);
     491             : 
     492           3 :         *aDefer = false;
     493           3 :         return piTarget->GetOrCreateListenerManager();
     494             :     }
     495             : 
     496         550 :     return nsStyledElement::GetEventListenerManagerForAttr(aAttrName, aDefer);
     497             : }
     498             : 
     499             : // returns true if the element is not a list
     500           0 : static bool IsNonList(mozilla::dom::NodeInfo* aNodeInfo)
     501             : {
     502           0 :   return !aNodeInfo->Equals(nsGkAtoms::tree) &&
     503           0 :          !aNodeInfo->Equals(nsGkAtoms::listbox) &&
     504           0 :          !aNodeInfo->Equals(nsGkAtoms::richlistbox);
     505             : }
     506             : 
     507             : bool
     508           3 : nsXULElement::IsFocusableInternal(int32_t *aTabIndex, bool aWithMouse)
     509             : {
     510             :   /*
     511             :    * Returns true if an element may be focused, and false otherwise. The inout
     512             :    * argument aTabIndex will be set to the tab order index to be used; -1 for
     513             :    * elements that should not be part of the tab order and a greater value to
     514             :    * indicate its tab order.
     515             :    *
     516             :    * Confusingly, the supplied value for the aTabIndex argument may indicate
     517             :    * whether the element may be focused as a result of the -moz-user-focus
     518             :    * property, where -1 means no and 0 means yes.
     519             :    *
     520             :    * For controls, the element cannot be focused and is not part of the tab
     521             :    * order if it is disabled.
     522             :    *
     523             :    * Controls (those that implement nsIDOMXULControlElement):
     524             :    *  *aTabIndex = -1  no tabindex     Not focusable or tabbable
     525             :    *  *aTabIndex = -1  tabindex="-1"   Not focusable or tabbable
     526             :    *  *aTabIndex = -1  tabindex=">=0"  Focusable and tabbable
     527             :    *  *aTabIndex >= 0  no tabindex     Focusable and tabbable
     528             :    *  *aTabIndex >= 0  tabindex="-1"   Focusable but not tabbable
     529             :    *  *aTabIndex >= 0  tabindex=">=0"  Focusable and tabbable
     530             :    * Non-controls:
     531             :    *  *aTabIndex = -1                  Not focusable or tabbable
     532             :    *  *aTabIndex >= 0                  Focusable and tabbable
     533             :    *
     534             :    * If aTabIndex is null, then the tabindex is not computed, and
     535             :    * true is returned for non-disabled controls and false otherwise.
     536             :    */
     537             : 
     538             :   // elements are not focusable by default
     539           3 :   bool shouldFocus = false;
     540             : 
     541             : #ifdef XP_MACOSX
     542             :   // on Mac, mouse interactions only focus the element if it's a list,
     543             :   // or if it's a remote target, since the remote target must handle
     544             :   // the focus.
     545             :   if (aWithMouse &&
     546             :       IsNonList(mNodeInfo) &&
     547             :       !EventStateManager::IsRemoteTarget(this))
     548             :   {
     549             :     return false;
     550             :   }
     551             : #endif
     552             : 
     553           6 :   nsCOMPtr<nsIDOMXULControlElement> xulControl = do_QueryObject(this);
     554           3 :   if (xulControl) {
     555             :     // a disabled element cannot be focused and is not part of the tab order
     556             :     bool disabled;
     557           0 :     xulControl->GetDisabled(&disabled);
     558           0 :     if (disabled) {
     559           0 :       if (aTabIndex)
     560           0 :         *aTabIndex = -1;
     561           0 :       return false;
     562             :     }
     563           0 :     shouldFocus = true;
     564             :   }
     565             : 
     566           3 :   if (aTabIndex) {
     567           3 :     if (xulControl) {
     568           0 :       if (HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
     569             :         // if either the aTabIndex argument or a specified tabindex is non-negative,
     570             :         // the element becomes focusable.
     571           0 :         int32_t tabIndex = 0;
     572           0 :         xulControl->GetTabIndex(&tabIndex);
     573           0 :         shouldFocus = *aTabIndex >= 0 || tabIndex >= 0;
     574           0 :         *aTabIndex = tabIndex;
     575             :       } else {
     576             :         // otherwise, if there is no tabindex attribute, just use the value of
     577             :         // *aTabIndex to indicate focusability. Reset any supplied tabindex to 0.
     578           0 :         shouldFocus = *aTabIndex >= 0;
     579           0 :         if (shouldFocus)
     580           0 :           *aTabIndex = 0;
     581             :       }
     582             : 
     583           0 :       if (shouldFocus && sTabFocusModelAppliesToXUL &&
     584           0 :           !(sTabFocusModel & eTabFocus_formElementsMask)) {
     585             :         // By default, the tab focus model doesn't apply to xul element on any system but OS X.
     586             :         // on OS X we're following it for UI elements (XUL) as sTabFocusModel is based on
     587             :         // "Full Keyboard Access" system setting (see mac/nsILookAndFeel).
     588             :         // both textboxes and list elements (i.e. trees and list) should always be focusable
     589             :         // (textboxes are handled as html:input)
     590             :         // For compatibility, we only do this for controls, otherwise elements like <browser>
     591             :         // cannot take this focus.
     592           0 :         if (IsNonList(mNodeInfo))
     593           0 :           *aTabIndex = -1;
     594             :       }
     595             :     } else {
     596           3 :       shouldFocus = *aTabIndex >= 0;
     597             :     }
     598             :   }
     599             : 
     600           3 :   return shouldFocus;
     601             : }
     602             : 
     603             : bool
     604           0 : nsXULElement::PerformAccesskey(bool aKeyCausesActivation,
     605             :                                bool aIsTrustedEvent)
     606             : {
     607           0 :     nsCOMPtr<nsIContent> content(this);
     608             : 
     609           0 :     if (IsXULElement(nsGkAtoms::label)) {
     610           0 :         nsCOMPtr<nsIDOMElement> element;
     611             : 
     612           0 :         nsAutoString control;
     613           0 :         GetAttr(kNameSpaceID_None, nsGkAtoms::control, control);
     614           0 :         if (!control.IsEmpty()) {
     615             :             //XXXsmaug Should we use ShadowRoot::GetElementById in case
     616             :             //         content is in Shadow DOM?
     617             :             nsCOMPtr<nsIDOMDocument> domDocument =
     618           0 :                 do_QueryInterface(content->GetUncomposedDoc());
     619           0 :             if (domDocument)
     620           0 :                 domDocument->GetElementById(control, getter_AddRefs(element));
     621             :         }
     622             :         // here we'll either change |content| to the element referenced by
     623             :         // |element|, or clear it.
     624           0 :         content = do_QueryInterface(element);
     625             : 
     626           0 :         if (!content) {
     627           0 :             return false;
     628             :         }
     629             :     }
     630             : 
     631           0 :     nsIFrame* frame = content->GetPrimaryFrame();
     632           0 :     if (!frame || !frame->IsVisibleConsideringAncestors()) {
     633           0 :         return false;
     634             :     }
     635             : 
     636           0 :     bool focused = false;
     637           0 :     nsXULElement* elm = FromContent(content);
     638           0 :     if (elm) {
     639             :         // Define behavior for each type of XUL element.
     640           0 :         if (!content->IsXULElement(nsGkAtoms::toolbarbutton)) {
     641           0 :           nsIFocusManager* fm = nsFocusManager::GetFocusManager();
     642           0 :           if (fm) {
     643           0 :             nsCOMPtr<nsIDOMElement> elementToFocus;
     644             :             // for radio buttons, focus the radiogroup instead
     645           0 :             if (content->IsXULElement(nsGkAtoms::radio)) {
     646           0 :               nsCOMPtr<nsIDOMXULSelectControlItemElement> controlItem(do_QueryInterface(content));
     647           0 :               if (controlItem) {
     648             :                 bool disabled;
     649           0 :                 controlItem->GetDisabled(&disabled);
     650           0 :                 if (!disabled) {
     651           0 :                   nsCOMPtr<nsIDOMXULSelectControlElement> selectControl;
     652           0 :                   controlItem->GetControl(getter_AddRefs(selectControl));
     653           0 :                   elementToFocus = do_QueryInterface(selectControl);
     654             :                 }
     655             :               }
     656             :             } else {
     657           0 :               elementToFocus = do_QueryInterface(content);
     658             :             }
     659           0 :             if (elementToFocus) {
     660           0 :               fm->SetFocus(elementToFocus, nsIFocusManager::FLAG_BYKEY);
     661             : 
     662             :               // Return true if the element became focused.
     663           0 :               nsPIDOMWindowOuter* window = OwnerDoc()->GetWindow();
     664           0 :               focused = (window && window->GetFocusedNode());
     665             :             }
     666             :           }
     667             :         }
     668           0 :         if (aKeyCausesActivation &&
     669           0 :             !content->IsAnyOfXULElements(nsGkAtoms::textbox, nsGkAtoms::menulist)) {
     670           0 :           elm->ClickWithInputSource(nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD, aIsTrustedEvent);
     671             :         }
     672             :     } else {
     673           0 :         return content->PerformAccesskey(aKeyCausesActivation, aIsTrustedEvent);
     674             :     }
     675             : 
     676           0 :     return focused;
     677             : }
     678             : 
     679             : //----------------------------------------------------------------------
     680             : 
     681             : void
     682        5437 : nsXULElement::AddListenerFor(const nsAttrName& aName,
     683             :                              bool aCompileEventHandlers)
     684             : {
     685             :     // If appropriate, add a popup listener and/or compile the event
     686             :     // handler. Called when we change the element's document, create a
     687             :     // new element, change an attribute's value, etc.
     688             :     // Eventlistenener-attributes are always in the null namespace
     689        5437 :     if (aName.IsAtom()) {
     690        5076 :         nsIAtom *attr = aName.Atom();
     691        5076 :         MaybeAddPopupListener(attr);
     692       10152 :         if (aCompileEventHandlers &&
     693        5076 :             nsContentUtils::IsEventAttributeName(attr, EventNameType_XUL)) {
     694         956 :             nsAutoString value;
     695         478 :             GetAttr(kNameSpaceID_None, attr, value);
     696         478 :             SetEventHandler(attr, value, true);
     697             :         }
     698             :     }
     699        5437 : }
     700             : 
     701             : void
     702        6049 : nsXULElement::MaybeAddPopupListener(nsIAtom* aLocalName)
     703             : {
     704             :     // If appropriate, add a popup listener. Called when we change the
     705             :     // element's document, create a new element, change an attribute's
     706             :     // value, etc.
     707       12098 :     if (aLocalName == nsGkAtoms::menu ||
     708       12097 :         aLocalName == nsGkAtoms::contextmenu ||
     709             :         // XXXdwh popup and context are deprecated
     710       12096 :         aLocalName == nsGkAtoms::popup ||
     711        6048 :         aLocalName == nsGkAtoms::context) {
     712          25 :         AddPopupListener(aLocalName);
     713             :     }
     714        6049 : }
     715             : 
     716             : //----------------------------------------------------------------------
     717             : //
     718             : // nsIContent interface
     719             : //
     720             : void
     721        3702 : nsXULElement::UpdateEditableState(bool aNotify)
     722             : {
     723             :     // Don't call through to Element here because the things
     724             :     // it does don't work for cases when we're an editable control.
     725        3702 :     nsIContent *parent = GetParent();
     726             : 
     727        3702 :     SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
     728        3702 :     UpdateState(aNotify);
     729        3702 : }
     730             : 
     731             : /**
     732             :  * Returns true if the user-agent style sheet rules for this XUL element are
     733             :  * in minimal-xul.css instead of xul.css.
     734             :  */
     735          30 : static inline bool XULElementsRulesInMinimalXULSheet(nsIAtom* aTag)
     736             : {
     737             :   return // scrollbar parts:
     738          56 :          aTag == nsGkAtoms::scrollbar ||
     739          36 :          aTag == nsGkAtoms::scrollbarbutton ||
     740          18 :          aTag == nsGkAtoms::scrollcorner ||
     741          12 :          aTag == nsGkAtoms::slider ||
     742           4 :          aTag == nsGkAtoms::thumb ||
     743           0 :          aTag == nsGkAtoms::scale ||
     744             :          // other
     745           0 :          aTag == nsGkAtoms::resizer ||
     746          30 :          aTag == nsGkAtoms::label ||
     747          30 :          aTag == nsGkAtoms::videocontrols;
     748             : }
     749             : 
     750             : #ifdef DEBUG
     751             : /**
     752             :  * Returns true if aElement is a XUL element created by the video controls
     753             :  * binding. HTML <video> and <audio> bindings pull in this binding. This
     754             :  * binding creates lots of different types of XUL elements.
     755             :  */
     756             : static inline bool
     757           0 : IsInVideoControls(nsXULElement* aElement)
     758             : {
     759           0 :   nsIContent* ancestor = aElement->GetParent();
     760           0 :   while (ancestor) {
     761           0 :     if (ancestor->NodeInfo()->Equals(nsGkAtoms::videocontrols, kNameSpaceID_XUL)) {
     762           0 :       return true;
     763             :     }
     764           0 :     ancestor = ancestor->GetParent();
     765             :   }
     766           0 :   return false;
     767             : }
     768             : 
     769             : /**
     770             :  * Returns true if aElement is an element created by the <binding
     771             :  * id="feedreaderUI"> binding or one of the bindings bound to such an element.
     772             :  * element in one of the binding for such an element. Only
     773             :  * subscribe.xhtml#feedSubscribeLine pulls in the feedreaderUI binding. This
     774             :  * binding creates lots of different types of XUL elements.
     775             :  */
     776             : bool
     777           0 : IsInFeedSubscribeLine(nsXULElement* aElement)
     778             : {
     779           0 :   nsIContent* bindingParent = aElement->GetBindingParent();
     780           0 :   if (bindingParent) {
     781           0 :     while (bindingParent->GetBindingParent()) {
     782           0 :       bindingParent = bindingParent->GetBindingParent();
     783             :     }
     784           0 :     nsIAtom* idAtom = bindingParent->GetID();
     785           0 :     if (idAtom && idAtom->Equals(NS_LITERAL_STRING("feedSubscribeLine"))) {
     786           0 :       return true;
     787             :     }
     788             :   }
     789           0 :   return false;
     790             : }
     791             : #endif
     792             : 
     793           0 : class XULInContentErrorReporter : public Runnable
     794             : {
     795             : public:
     796           0 :   explicit XULInContentErrorReporter(nsIDocument* aDocument)
     797           0 :     : mozilla::Runnable("XULInContentErrorReporter")
     798           0 :     , mDocument(aDocument)
     799             :   {
     800           0 :   }
     801             : 
     802           0 :   NS_IMETHOD Run() override
     803             :   {
     804           0 :     mDocument->WarnOnceAbout(nsIDocument::eImportXULIntoContent, false);
     805           0 :     return NS_OK;
     806             :   }
     807             : 
     808             : private:
     809             :   nsCOMPtr<nsIDocument> mDocument;
     810             : };
     811             : 
     812             : nsresult
     813        3702 : nsXULElement::BindToTree(nsIDocument* aDocument,
     814             :                          nsIContent* aParent,
     815             :                          nsIContent* aBindingParent,
     816             :                          bool aCompileEventHandlers)
     817             : {
     818        6850 :   if (!aBindingParent &&
     819        1699 :       aDocument &&
     820        2999 :       !aDocument->IsLoadedAsInteractiveData() &&
     821        5002 :       !aDocument->AllowXULXBL() &&
     822           0 :       !aDocument->HasWarnedAbout(nsIDocument::eImportXULIntoContent)) {
     823           0 :     nsContentUtils::AddScriptRunner(new XULInContentErrorReporter(aDocument));
     824             :   }
     825             : 
     826        3702 :   nsresult rv = nsStyledElement::BindToTree(aDocument, aParent,
     827             :                                             aBindingParent,
     828        3702 :                                             aCompileEventHandlers);
     829        3702 :   NS_ENSURE_SUCCESS(rv, rv);
     830             : 
     831        3702 :   nsIDocument* doc = GetComposedDoc();
     832        5953 :   if (doc &&
     833        3732 :       !doc->LoadsFullXULStyleSheetUpFront() &&
     834          30 :       !doc->IsUnstyledDocument()) {
     835             : 
     836             :     // To save CPU cycles and memory, non-XUL documents only load the user
     837             :     // agent style sheet rules for a minimal set of XUL elements such as
     838             :     // 'scrollbar' that may be created implicitly for their content (those
     839             :     // rules being in minimal-xul.css).  This is where we make sure that all
     840             :     // the other XUL UA style sheet rules (xul.css) have been loaded if the
     841             :     // minimal set is not sufficient.
     842             :     //
     843             :     // We do this during binding, not element construction, because elements
     844             :     // can be moved from the document that creates them to another document.
     845             : 
     846          30 :     if (!XULElementsRulesInMinimalXULSheet(NodeInfo()->NameAtom())) {
     847           0 :       auto cache = nsLayoutStylesheetCache::For(doc->GetStyleBackendType());
     848           0 :       doc->EnsureOnDemandBuiltInUASheet(cache->XULSheet());
     849             :       // To keep memory usage down it is important that we try and avoid
     850             :       // pulling xul.css into non-XUL documents. That should be very rare, and
     851             :       // for HTML we currently should only pull it in if the document contains
     852             :       // an <audio> or <video> element. This assertion is here to make sure
     853             :       // that we don't fail to notice if a change to bindings causes us to
     854             :       // start pulling in xul.css much more frequently. If this assertion
     855             :       // fails then we need to figure out why, and how we can continue to avoid
     856             :       // pulling in xul.css.
     857             :       // Note that add-ons may introduce bindings that cause this assertion to
     858             :       // fire.
     859           0 :       NS_ASSERTION(IsInVideoControls(this) ||
     860             :                    IsInFeedSubscribeLine(this) ||
     861             :                    IsXULElement(nsGkAtoms::datetimebox),
     862             :                    "Unexpected XUL element in non-XUL doc");
     863             :     }
     864             :   }
     865             : 
     866        3702 :   if (aDocument) {
     867        2251 :       NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
     868             :                    "Missing a script blocker!");
     869             :       // We're in a document now.  Kick off the frame load.
     870        2251 :       LoadSrc();
     871             :   }
     872             : 
     873        3702 :   return rv;
     874             : }
     875             : 
     876             : void
     877         716 : nsXULElement::UnbindFromTree(bool aDeep, bool aNullParent)
     878             : {
     879             :     // mControllers can own objects that are implemented
     880             :     // in JavaScript (such as some implementations of
     881             :     // nsIControllers.  These objects prevent their global
     882             :     // object's script object from being garbage collected,
     883             :     // which means JS continues to hold an owning reference
     884             :     // to the nsGlobalWindow, which owns the document,
     885             :     // which owns this content.  That's a cycle, so we break
     886             :     // it here.  (It might be better to break this by releasing
     887             :     // mDocument in nsGlobalWindow::SetDocShell, but I'm not
     888             :     // sure whether that would fix all possible cycles through
     889             :     // mControllers.)
     890         716 :     nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingDOMSlots());
     891         716 :     if (slots) {
     892          20 :         NS_IF_RELEASE(slots->mControllers);
     893          40 :         RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
     894          20 :         if (frameLoader) {
     895           1 :             frameLoader->Destroy();
     896             :         }
     897          20 :         slots->mFrameLoaderOrOpener = nullptr;
     898             :     }
     899             : 
     900         716 :     nsStyledElement::UnbindFromTree(aDeep, aNullParent);
     901         716 : }
     902             : 
     903             : void
     904          68 : nsXULElement::RemoveChildAt(uint32_t aIndex, bool aNotify)
     905             : {
     906         136 :     nsCOMPtr<nsIContent> oldKid = mAttrsAndChildren.GetSafeChildAt(aIndex);
     907          68 :     if (!oldKid) {
     908           0 :       return;
     909             :     }
     910             : 
     911             :     // On the removal of a <treeitem>, <treechildren>, or <treecell> element,
     912             :     // the possibility exists that some of the items in the removed subtree
     913             :     // are selected (and therefore need to be deselected). We need to account for this.
     914         136 :     nsCOMPtr<nsIDOMXULMultiSelectControlElement> controlElement;
     915         136 :     nsCOMPtr<nsIListBoxObject> listBox;
     916          68 :     bool fireSelectionHandler = false;
     917             : 
     918             :     // -1 = do nothing, -2 = null out current item
     919             :     // anything else = index to re-set as current
     920          68 :     int32_t newCurrentIndex = -1;
     921             : 
     922          68 :     if (oldKid->NodeInfo()->Equals(nsGkAtoms::listitem, kNameSpaceID_XUL)) {
     923             :       // This is the nasty case. We have (potentially) a slew of selected items
     924             :       // and cells going away.
     925             :       // First, retrieve the tree.
     926             :       // Check first whether this element IS the tree
     927           0 :       controlElement = do_QueryObject(this);
     928             : 
     929             :       // If it's not, look at our parent
     930           0 :       if (!controlElement)
     931           0 :         GetParentTree(getter_AddRefs(controlElement));
     932           0 :       nsCOMPtr<nsIContent> controlContent(do_QueryInterface(controlElement));
     933           0 :       RefPtr<nsXULElement> xulElement = FromContentOrNull(controlContent);
     934             : 
     935           0 :       nsCOMPtr<nsIDOMElement> oldKidElem = do_QueryInterface(oldKid);
     936           0 :       if (xulElement && oldKidElem) {
     937             :         // Iterate over all of the items and find out if they are contained inside
     938             :         // the removed subtree.
     939             :         int32_t length;
     940           0 :         controlElement->GetSelectedCount(&length);
     941           0 :         for (int32_t i = 0; i < length; i++) {
     942           0 :           nsCOMPtr<nsIDOMXULSelectControlItemElement> node;
     943           0 :           controlElement->MultiGetSelectedItem(i, getter_AddRefs(node));
     944             :           // we need to QI here to do an XPCOM-correct pointercompare
     945           0 :           nsCOMPtr<nsIDOMElement> selElem = do_QueryInterface(node);
     946           0 :           if (selElem == oldKidElem &&
     947           0 :               NS_SUCCEEDED(controlElement->RemoveItemFromSelection(node))) {
     948           0 :             length--;
     949           0 :             i--;
     950           0 :             fireSelectionHandler = true;
     951             :           }
     952             :         }
     953             : 
     954           0 :         nsCOMPtr<nsIDOMXULSelectControlItemElement> curItem;
     955           0 :         controlElement->GetCurrentItem(getter_AddRefs(curItem));
     956           0 :         nsCOMPtr<nsIContent> curNode = do_QueryInterface(curItem);
     957           0 :         if (curNode && nsContentUtils::ContentIsDescendantOf(curNode, oldKid)) {
     958             :             // Current item going away
     959           0 :             IgnoredErrorResult ignored;
     960           0 :             nsCOMPtr<nsIBoxObject> box = xulElement->GetBoxObject(ignored);
     961           0 :             listBox = do_QueryInterface(box);
     962           0 :             if (listBox && oldKidElem) {
     963           0 :               listBox->GetIndexOfItem(oldKidElem, &newCurrentIndex);
     964             :             }
     965             : 
     966             :             // If any of this fails, we'll just set the current item to null
     967           0 :             if (newCurrentIndex == -1)
     968           0 :               newCurrentIndex = -2;
     969             :         }
     970             :       }
     971             :     }
     972             : 
     973          68 :     nsStyledElement::RemoveChildAt(aIndex, aNotify);
     974             : 
     975          68 :     if (newCurrentIndex == -2) {
     976           0 :         controlElement->SetCurrentItem(nullptr);
     977          68 :     } else if (newCurrentIndex > -1) {
     978             :         // Make sure the index is still valid
     979             :         int32_t treeRows;
     980           0 :         listBox->GetRowCount(&treeRows);
     981           0 :         if (treeRows > 0) {
     982           0 :             newCurrentIndex = std::min((treeRows - 1), newCurrentIndex);
     983           0 :             nsCOMPtr<nsIDOMElement> newCurrentItem;
     984           0 :             listBox->GetItemAtIndex(newCurrentIndex, getter_AddRefs(newCurrentItem));
     985           0 :             nsCOMPtr<nsIDOMXULSelectControlItemElement> xulCurItem = do_QueryInterface(newCurrentItem);
     986           0 :             if (xulCurItem)
     987           0 :                 controlElement->SetCurrentItem(xulCurItem);
     988             :         } else {
     989           0 :             controlElement->SetCurrentItem(nullptr);
     990             :         }
     991             :     }
     992             : 
     993             :     nsIDocument* doc;
     994          68 :     if (fireSelectionHandler && (doc = GetComposedDoc())) {
     995           0 :       nsContentUtils::DispatchTrustedEvent(doc,
     996             :                                            static_cast<nsIContent*>(this),
     997           0 :                                            NS_LITERAL_STRING("select"),
     998             :                                            false,
     999           0 :                                            true);
    1000             :     }
    1001             : }
    1002             : 
    1003             : void
    1004          15 : nsXULElement::UnregisterAccessKey(const nsAString& aOldValue)
    1005             : {
    1006             :     // If someone changes the accesskey, unregister the old one
    1007             :     //
    1008          15 :     nsIDocument* doc = GetComposedDoc();
    1009          15 :     if (doc && !aOldValue.IsEmpty()) {
    1010          15 :         nsIPresShell *shell = doc->GetShell();
    1011             : 
    1012          15 :         if (shell) {
    1013          15 :             nsIContent *content = this;
    1014             : 
    1015             :             // find out what type of content node this is
    1016          15 :             if (mNodeInfo->Equals(nsGkAtoms::label)) {
    1017             :                 // For anonymous labels the unregistering must
    1018             :                 // occur on the binding parent control.
    1019             :                 // XXXldb: And what if the binding parent is null?
    1020           3 :                 content = GetBindingParent();
    1021             :             }
    1022             : 
    1023          15 :             if (content) {
    1024             :                 shell->GetPresContext()->EventStateManager()->
    1025          15 :                     UnregisterAccessKey(content, aOldValue.First());
    1026             :             }
    1027             :         }
    1028             :     }
    1029          15 : }
    1030             : 
    1031             : nsresult
    1032        1035 : nsXULElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
    1033             :                             const nsAttrValueOrString* aValue, bool aNotify)
    1034             : {
    1035        1096 :     if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::accesskey &&
    1036          61 :         IsInUncomposedDoc()) {
    1037          84 :         nsAutoString oldValue;
    1038          42 :         if (GetAttr(aNamespaceID, aName, oldValue)) {
    1039          15 :             UnregisterAccessKey(oldValue);
    1040             :         }
    1041        1964 :     } else if (aNamespaceID == kNameSpaceID_None &&
    1042        1964 :                (aName == nsGkAtoms::command || aName == nsGkAtoms::observes) &&
    1043           9 :                IsInUncomposedDoc()) {
    1044             : //         XXX sXBL/XBL2 issue! Owner or current document?
    1045          18 :         nsAutoString oldValue;
    1046           9 :         GetAttr(kNameSpaceID_None, nsGkAtoms::observes, oldValue);
    1047           9 :         if (oldValue.IsEmpty()) {
    1048           9 :           GetAttr(kNameSpaceID_None, nsGkAtoms::command, oldValue);
    1049             :         }
    1050             : 
    1051           9 :         if (!oldValue.IsEmpty()) {
    1052           9 :           RemoveBroadcaster(oldValue);
    1053             :         }
    1054        1946 :     } else if (aNamespaceID == kNameSpaceID_None &&
    1055         922 :                aValue &&
    1056        1911 :                mNodeInfo->Equals(nsGkAtoms::window) &&
    1057           5 :                aName == nsGkAtoms::chromemargin) {
    1058           0 :       nsAttrValue attrValue;
    1059             :       // Make sure the margin format is valid first
    1060           0 :       if (!attrValue.ParseIntMarginValue(aValue->String())) {
    1061           0 :         return NS_ERROR_INVALID_ARG;
    1062             :       }
    1063        1946 :     } else if (aNamespaceID == kNameSpaceID_None &&
    1064         962 :                aName == nsGkAtoms::usercontextid) {
    1065           0 :         nsAutoString oldValue;
    1066           0 :         bool hasAttribute = GetAttr(kNameSpaceID_None, nsGkAtoms::usercontextid, oldValue);
    1067           0 :         if (hasAttribute && (!aValue || !aValue->String().Equals(oldValue))) {
    1068           0 :           MOZ_ASSERT(false, "Changing usercontextid is not allowed.");
    1069             :           return NS_ERROR_INVALID_ARG;
    1070             :         }
    1071             :     }
    1072             : 
    1073        1035 :     return nsStyledElement::BeforeSetAttr(aNamespaceID, aName,
    1074        1035 :                                           aValue, aNotify);
    1075             : }
    1076             : 
    1077             : nsresult
    1078        1035 : nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
    1079             :                            const nsAttrValue* aValue,
    1080             :                            const nsAttrValue* aOldValue, bool aNotify)
    1081             : {
    1082        1035 :     if (aNamespaceID == kNameSpaceID_None) {
    1083        1013 :         if (aValue) {
    1084             :             // Add popup and event listeners. We can't call AddListenerFor since
    1085             :             // the attribute isn't set yet.
    1086         973 :             MaybeAddPopupListener(aName);
    1087         973 :             if (nsContentUtils::IsEventAttributeName(aName, EventNameType_XUL)) {
    1088          75 :                 if (aValue->Type() == nsAttrValue::eString) {
    1089          60 :                     SetEventHandler(aName, aValue->GetStringValue(), true);
    1090             :                 } else {
    1091          30 :                     nsAutoString body;
    1092          15 :                     aValue->ToString(body);
    1093          15 :                     SetEventHandler(aName, body, true);
    1094             :                 }
    1095             :             }
    1096             : 
    1097         973 :             nsIDocument* document = GetUncomposedDoc();
    1098             : 
    1099             :             // Hide chrome if needed
    1100         973 :             if (mNodeInfo->Equals(nsGkAtoms::window)) {
    1101           5 :                 if (aName == nsGkAtoms::hidechrome) {
    1102           0 :                     HideWindowChrome(
    1103           0 :                       aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
    1104           5 :                 } else if (aName == nsGkAtoms::chromemargin) {
    1105           0 :                     SetChromeMargins(aValue);
    1106          10 :                 } else if (aName == nsGkAtoms::windowtype &&
    1107           5 :                            document && document->GetRootElement() == this) {
    1108           0 :                     MaybeUpdatePrivateLifetime();
    1109             :                 }
    1110             :             }
    1111             :             // title, (in)activetitlebarcolor and drawintitlebar are settable on
    1112             :             // any root node (windows, dialogs, etc)
    1113         973 :             if (document && document->GetRootElement() == this) {
    1114           5 :                 if (aName == nsGkAtoms::title) {
    1115           0 :                     document->NotifyPossibleTitleChange(false);
    1116          10 :                 } else if ((aName == nsGkAtoms::activetitlebarcolor ||
    1117           5 :                             aName == nsGkAtoms::inactivetitlebarcolor)) {
    1118           0 :                     nscolor color = NS_RGBA(0, 0, 0, 0);
    1119           0 :                     if (aValue->Type() == nsAttrValue::eColor) {
    1120           0 :                         aValue->GetColorValue(color);
    1121             :                     } else {
    1122           0 :                         nsAutoString tmp;
    1123           0 :                         nsAttrValue attrValue;
    1124           0 :                         aValue->ToString(tmp);
    1125           0 :                         attrValue.ParseColor(tmp);
    1126           0 :                         attrValue.GetColorValue(color);
    1127             :                     }
    1128           0 :                     SetTitlebarColor(color, aName == nsGkAtoms::activetitlebarcolor);
    1129           5 :                 } else if (aName == nsGkAtoms::drawintitlebar) {
    1130           0 :                     SetDrawsInTitlebar(
    1131           0 :                         aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
    1132           5 :                 } else if (aName == nsGkAtoms::drawtitle) {
    1133           0 :                     SetDrawsTitle(
    1134           0 :                         aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters));
    1135           5 :                 } else if (aName == nsGkAtoms::localedir) {
    1136             :                     // if the localedir changed on the root element, reset the document direction
    1137           0 :                     nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(document);
    1138           0 :                     if (xuldoc) {
    1139           0 :                         xuldoc->ResetDocumentDirection();
    1140             :                     }
    1141          10 :                 } else if (aName == nsGkAtoms::lwtheme ||
    1142           5 :                          aName == nsGkAtoms::lwthemetextcolor) {
    1143             :                     // if the lwtheme changed, make sure to reset the document lwtheme cache
    1144           0 :                     nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(document);
    1145           0 :                     if (xuldoc) {
    1146           0 :                         xuldoc->ResetDocumentLWTheme();
    1147           0 :                         UpdateBrightTitlebarForeground(document);
    1148           0 :                     }
    1149           5 :                 } else if (aName == nsGkAtoms::brighttitlebarforeground) {
    1150           0 :                     UpdateBrightTitlebarForeground(document);
    1151             :                 }
    1152             :             }
    1153             : 
    1154         973 :             if (aName == nsGkAtoms::src && document) {
    1155           1 :                 LoadSrc();
    1156             :             }
    1157             :         } else {
    1158          40 :             if (mNodeInfo->Equals(nsGkAtoms::window)) {
    1159           0 :                 if (aName == nsGkAtoms::hidechrome) {
    1160           0 :                     HideWindowChrome(false);
    1161           0 :                 } else if (aName == nsGkAtoms::chromemargin) {
    1162           0 :                     ResetChromeMargins();
    1163             :                 }
    1164             :             }
    1165             : 
    1166          40 :             nsIDocument* doc = GetUncomposedDoc();
    1167          40 :             if (doc && doc->GetRootElement() == this) {
    1168           0 :                 if ((aName == nsGkAtoms::activetitlebarcolor ||
    1169           0 :                      aName == nsGkAtoms::inactivetitlebarcolor)) {
    1170             :                     // Use 0, 0, 0, 0 as the "none" color.
    1171           0 :                     SetTitlebarColor(NS_RGBA(0, 0, 0, 0), aName == nsGkAtoms::activetitlebarcolor);
    1172           0 :                 } else if (aName == nsGkAtoms::localedir) {
    1173             :                     // if the localedir changed on the root element, reset the document direction
    1174           0 :                     nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(doc);
    1175           0 :                     if (xuldoc) {
    1176           0 :                         xuldoc->ResetDocumentDirection();
    1177             :                     }
    1178           0 :                 } else if ((aName == nsGkAtoms::lwtheme ||
    1179           0 :                             aName == nsGkAtoms::lwthemetextcolor)) {
    1180             :                     // if the lwtheme changed, make sure to restyle appropriately
    1181           0 :                     nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(doc);
    1182           0 :                     if (xuldoc) {
    1183           0 :                         xuldoc->ResetDocumentLWTheme();
    1184           0 :                         UpdateBrightTitlebarForeground(doc);
    1185           0 :                     }
    1186           0 :                 } else if (aName == nsGkAtoms::brighttitlebarforeground) {
    1187           0 :                     UpdateBrightTitlebarForeground(doc);
    1188           0 :                 } else if (aName == nsGkAtoms::drawintitlebar) {
    1189           0 :                     SetDrawsInTitlebar(false);
    1190           0 :                 } else if (aName == nsGkAtoms::drawtitle) {
    1191           0 :                     SetDrawsTitle(false);
    1192             :                 }
    1193             :             }
    1194             :         }
    1195             : 
    1196             :         // XXX need to check if they're changing an event handler: if
    1197             :         // so, then we need to unhook the old one.  Or something.
    1198             :     }
    1199             : 
    1200        1035 :     return nsStyledElement::AfterSetAttr(aNamespaceID, aName,
    1201        1035 :                                          aValue, aOldValue, aNotify);
    1202             : }
    1203             : 
    1204             : bool
    1205         969 : nsXULElement::ParseAttribute(int32_t aNamespaceID,
    1206             :                              nsIAtom* aAttribute,
    1207             :                              const nsAString& aValue,
    1208             :                              nsAttrValue& aResult)
    1209             : {
    1210             :     // Parse into a nsAttrValue
    1211         969 :     if (!nsStyledElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
    1212             :                                          aResult)) {
    1213             :         // Fall back to parsing as atom for short values
    1214         918 :         aResult.ParseStringOrAtom(aValue);
    1215             :     }
    1216             : 
    1217         969 :     return true;
    1218             : }
    1219             : 
    1220             : void
    1221           9 : nsXULElement::RemoveBroadcaster(const nsAString & broadcasterId)
    1222             : {
    1223          18 :     nsCOMPtr<nsIDOMXULDocument> xuldoc = do_QueryInterface(OwnerDoc());
    1224           9 :     if (xuldoc) {
    1225          18 :         nsCOMPtr<nsIDOMElement> broadcaster;
    1226          18 :         nsCOMPtr<nsIDOMDocument> domDoc (do_QueryInterface(xuldoc));
    1227           9 :         domDoc->GetElementById(broadcasterId, getter_AddRefs(broadcaster));
    1228           9 :         if (broadcaster) {
    1229          18 :             xuldoc->RemoveBroadcastListenerFor(broadcaster, this,
    1230          18 :               NS_LITERAL_STRING("*"));
    1231             :         }
    1232             :     }
    1233           9 : }
    1234             : 
    1235             : void
    1236           0 : nsXULElement::DestroyContent()
    1237             : {
    1238           0 :     nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingDOMSlots());
    1239           0 :     if (slots) {
    1240           0 :         NS_IF_RELEASE(slots->mControllers);
    1241           0 :         RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
    1242           0 :         if (frameLoader) {
    1243           0 :             frameLoader->Destroy();
    1244             :         }
    1245           0 :         slots->mFrameLoaderOrOpener = nullptr;
    1246             :     }
    1247             : 
    1248           0 :     nsStyledElement::DestroyContent();
    1249           0 : }
    1250             : 
    1251             : #ifdef DEBUG
    1252             : void
    1253           0 : nsXULElement::List(FILE* out, int32_t aIndent) const
    1254             : {
    1255           0 :     nsCString prefix("XUL");
    1256           0 :     if (HasSlots()) {
    1257           0 :       prefix.Append('*');
    1258             :     }
    1259           0 :     prefix.Append(' ');
    1260             : 
    1261           0 :     nsStyledElement::List(out, aIndent, prefix);
    1262           0 : }
    1263             : #endif
    1264             : 
    1265             : bool
    1266        1302 : nsXULElement::IsEventStoppedFromAnonymousScrollbar(EventMessage aMessage)
    1267             : {
    1268        1302 :     return (IsRootOfNativeAnonymousSubtree() &&
    1269        1302 :             IsAnyOfXULElements(nsGkAtoms::scrollbar, nsGkAtoms::scrollcorner) &&
    1270           0 :             (aMessage == eMouseClick || aMessage == eMouseDoubleClick ||
    1271           0 :              aMessage == eXULCommand || aMessage == eContextMenu ||
    1272        1302 :              aMessage == eDragStart  || aMessage == eMouseAuxClick));
    1273             : }
    1274             : 
    1275             : nsresult
    1276           0 : nsXULElement::DispatchXULCommand(const EventChainVisitor& aVisitor,
    1277             :                                  nsAutoString& aCommand)
    1278             : {
    1279             :     // XXX sXBL/XBL2 issue! Owner or current document?
    1280           0 :     nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(GetUncomposedDoc()));
    1281           0 :     NS_ENSURE_STATE(domDoc);
    1282           0 :     nsCOMPtr<nsIDOMElement> commandElt;
    1283           0 :     domDoc->GetElementById(aCommand, getter_AddRefs(commandElt));
    1284           0 :     nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt));
    1285           0 :     if (commandContent) {
    1286             :         // Create a new command event to dispatch to the element
    1287             :         // pointed to by the command attribute. The new event's
    1288             :         // sourceEvent will be the original command event that we're
    1289             :         // handling.
    1290           0 :         nsCOMPtr<nsIDOMEvent> domEvent = aVisitor.mDOMEvent;
    1291           0 :         while (domEvent) {
    1292           0 :             Event* event = domEvent->InternalDOMEvent();
    1293           0 :             NS_ENSURE_STATE(!SameCOMIdentity(event->GetOriginalTarget(),
    1294             :                                             commandContent));
    1295             :             nsCOMPtr<nsIDOMXULCommandEvent> commandEvent =
    1296           0 :                 do_QueryInterface(domEvent);
    1297           0 :             if (commandEvent) {
    1298           0 :                 commandEvent->GetSourceEvent(getter_AddRefs(domEvent));
    1299             :             } else {
    1300           0 :                 domEvent = nullptr;
    1301             :             }
    1302             :         }
    1303           0 :         WidgetInputEvent* orig = aVisitor.mEvent->AsInputEvent();
    1304           0 :         nsContentUtils::DispatchXULCommand(
    1305             :           commandContent,
    1306           0 :           orig->IsTrusted(),
    1307           0 :           aVisitor.mDOMEvent,
    1308             :           nullptr,
    1309           0 :           orig->IsControl(),
    1310           0 :           orig->IsAlt(),
    1311           0 :           orig->IsShift(),
    1312           0 :           orig->IsMeta());
    1313             :     } else {
    1314           0 :         NS_WARNING("A XUL element is attached to a command that doesn't exist!\n");
    1315             :     }
    1316           0 :     return NS_OK;
    1317             : }
    1318             : 
    1319             : nsresult
    1320        1302 : nsXULElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
    1321             : {
    1322        1302 :     aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119
    1323        1302 :     if (IsEventStoppedFromAnonymousScrollbar(aVisitor.mEvent->mMessage)) {
    1324             :         // Don't propagate these events from native anonymous scrollbar.
    1325           0 :         aVisitor.mCanHandle = true;
    1326           0 :         aVisitor.mParentTarget = nullptr;
    1327           0 :         return NS_OK;
    1328             :     }
    1329        2604 :     if (aVisitor.mEvent->mMessage == eXULCommand &&
    1330           0 :         aVisitor.mEvent->mClass == eInputEventClass &&
    1331        1302 :         aVisitor.mEvent->mOriginalTarget == static_cast<nsIContent*>(this) &&
    1332           0 :         !IsXULElement(nsGkAtoms::command)) {
    1333             :         // Check that we really have an xul command event. That will be handled
    1334             :         // in a special way.
    1335             :         nsCOMPtr<nsIDOMXULCommandEvent> xulEvent =
    1336           0 :             do_QueryInterface(aVisitor.mDOMEvent);
    1337             :         // See if we have a command elt.  If so, we execute on the command
    1338             :         // instead of on our content element.
    1339           0 :         nsAutoString command;
    1340           0 :         if (xulEvent &&
    1341           0 :             GetAttr(kNameSpaceID_None, nsGkAtoms::command, command) &&
    1342           0 :             !command.IsEmpty()) {
    1343             :             // Stop building the event target chain for the original event.
    1344             :             // We don't want it to propagate to any DOM nodes.
    1345           0 :             aVisitor.mCanHandle = false;
    1346           0 :             aVisitor.mAutomaticChromeDispatch = false;
    1347             :             // Dispatch XUL command in PreHandleEvent to prevent it breaks event
    1348             :             // target chain creation
    1349           0 :             aVisitor.mWantsPreHandleEvent = true;
    1350           0 :             aVisitor.mItemFlags |= NS_DISPATCH_XUL_COMMAND;
    1351           0 :             return NS_OK;
    1352             :         }
    1353             :     }
    1354             : 
    1355        1302 :     return nsStyledElement::GetEventTargetParent(aVisitor);
    1356             : }
    1357             : 
    1358             : nsresult
    1359           0 : nsXULElement::PreHandleEvent(EventChainVisitor& aVisitor)
    1360             : {
    1361           0 :     if (aVisitor.mItemFlags & NS_DISPATCH_XUL_COMMAND) {
    1362           0 :         nsAutoString command;
    1363           0 :         GetAttr(kNameSpaceID_None, nsGkAtoms::command, command);
    1364           0 :         MOZ_ASSERT(!command.IsEmpty());
    1365           0 :         return DispatchXULCommand(aVisitor, command);
    1366             :     }
    1367           0 :     return nsStyledElement::PreHandleEvent(aVisitor);
    1368             : }
    1369             : 
    1370             : // XXX This _should_ be an implementation method, _not_ publicly exposed :-(
    1371             : already_AddRefed<nsIRDFResource>
    1372           0 : nsXULElement::GetResource(ErrorResult& rv)
    1373             : {
    1374           0 :     nsAutoString id;
    1375           0 :     GetAttr(kNameSpaceID_None, nsGkAtoms::ref, id);
    1376           0 :     if (id.IsEmpty()) {
    1377           0 :         GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
    1378             :     }
    1379             : 
    1380           0 :     if (id.IsEmpty()) {
    1381           0 :         return nullptr;
    1382             :     }
    1383             : 
    1384           0 :     nsCOMPtr<nsIRDFResource> resource;
    1385           0 :     rv = nsXULContentUtils::RDFService()->
    1386           0 :         GetUnicodeResource(id, getter_AddRefs(resource));
    1387           0 :     return resource.forget();
    1388             : }
    1389             : 
    1390             : already_AddRefed<nsIRDFCompositeDataSource>
    1391        1888 : nsXULElement::GetDatabase()
    1392             : {
    1393        3776 :     nsCOMPtr<nsIXULTemplateBuilder> builder = GetBuilder();
    1394        1888 :     if (!builder) {
    1395        1888 :         return nullptr;
    1396             :     }
    1397             : 
    1398           0 :     nsCOMPtr<nsIRDFCompositeDataSource> database;
    1399           0 :     builder->GetDatabase(getter_AddRefs(database));
    1400           0 :     return database.forget();
    1401             : }
    1402             : 
    1403             : 
    1404             : already_AddRefed<nsIXULTemplateBuilder>
    1405        1888 : nsXULElement::GetBuilder()
    1406             : {
    1407             :     // XXX sXBL/XBL2 issue! Owner or current document?
    1408        3776 :     nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(GetUncomposedDoc());
    1409        1888 :     if (!xuldoc) {
    1410           0 :         return nullptr;
    1411             :     }
    1412             : 
    1413        3776 :     nsCOMPtr<nsIXULTemplateBuilder> builder;
    1414        1888 :     xuldoc->GetTemplateBuilderFor(this, getter_AddRefs(builder));
    1415        1888 :     return builder.forget();
    1416             : }
    1417             : 
    1418             : //----------------------------------------------------------------------
    1419             : // Implementation methods
    1420             : 
    1421             : NS_IMETHODIMP
    1422        2091 : nsXULElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
    1423             : {
    1424        2091 :     return NS_OK;
    1425             : }
    1426             : 
    1427             : nsChangeHint
    1428         321 : nsXULElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
    1429             :                                      int32_t aModType) const
    1430             : {
    1431         321 :     nsChangeHint retval(nsChangeHint(0));
    1432             : 
    1433         321 :     if (aAttribute == nsGkAtoms::value &&
    1434          14 :         (aModType == nsIDOMMutationEvent::REMOVAL ||
    1435             :          aModType == nsIDOMMutationEvent::ADDITION)) {
    1436          12 :       if (IsAnyOfXULElements(nsGkAtoms::label, nsGkAtoms::description))
    1437             :         // Label and description dynamically morph between a normal
    1438             :         // block and a cropping single-line XUL text frame.  If the
    1439             :         // value attribute is being added or removed, then we need to
    1440             :         // return a hint of frame change.  (See bugzilla bug 95475 for
    1441             :         // details.)
    1442           5 :         retval = nsChangeHint_ReconstructFrame;
    1443             :     } else {
    1444             :         // if left or top changes we reflow. This will happen in xul
    1445             :         // containers that manage positioned children such as a stack.
    1446         630 :         if (nsGkAtoms::left == aAttribute || nsGkAtoms::top == aAttribute ||
    1447         945 :             nsGkAtoms::right == aAttribute || nsGkAtoms::bottom == aAttribute ||
    1448         630 :             nsGkAtoms::start == aAttribute || nsGkAtoms::end == aAttribute)
    1449           0 :             retval = NS_STYLE_HINT_REFLOW;
    1450             :     }
    1451             : 
    1452         321 :     return retval;
    1453             : }
    1454             : 
    1455             : NS_IMETHODIMP_(bool)
    1456        1303 : nsXULElement::IsAttributeMapped(const nsIAtom* aAttribute) const
    1457             : {
    1458        1303 :     return false;
    1459             : }
    1460             : 
    1461             : nsIControllers*
    1462          12 : nsXULElement::GetControllers(ErrorResult& rv)
    1463             : {
    1464          12 :     if (! Controllers()) {
    1465           1 :         nsDOMSlots* slots = DOMSlots();
    1466             : 
    1467           1 :         rv = NS_NewXULControllers(nullptr, NS_GET_IID(nsIControllers),
    1468           2 :                                   reinterpret_cast<void**>(&slots->mControllers));
    1469             : 
    1470           1 :         NS_ASSERTION(!rv.Failed(), "unable to create a controllers");
    1471           1 :         if (rv.Failed()) {
    1472           0 :             return nullptr;
    1473             :         }
    1474             :     }
    1475             : 
    1476          12 :     return Controllers();
    1477             : }
    1478             : 
    1479             : already_AddRefed<BoxObject>
    1480          12 : nsXULElement::GetBoxObject(ErrorResult& rv)
    1481             : {
    1482             :     // XXX sXBL/XBL2 issue! Owner or current document?
    1483          12 :     return OwnerDoc()->GetBoxObjectFor(this, rv);
    1484             : }
    1485             : 
    1486             : nsresult
    1487        2252 : nsXULElement::LoadSrc()
    1488             : {
    1489             :     // Allow frame loader only on objects for which a container box object
    1490             :     // can be obtained.
    1491        2252 :     if (!IsAnyOfXULElements(nsGkAtoms::browser, nsGkAtoms::editor,
    1492             :                             nsGkAtoms::iframe)) {
    1493        2248 :         return NS_OK;
    1494             :     }
    1495          12 :     if (!IsInUncomposedDoc() ||
    1496           8 :         !OwnerDoc()->GetRootElement() ||
    1497           4 :         OwnerDoc()->GetRootElement()->
    1498           8 :             NodeInfo()->Equals(nsGkAtoms::overlay, kNameSpaceID_XUL)) {
    1499           0 :         return NS_OK;
    1500             :     }
    1501           8 :     RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
    1502           4 :     if (!frameLoader) {
    1503             :         // Check if we have an opener we need to be setting
    1504           4 :         nsXULSlots* slots = static_cast<nsXULSlots*>(Slots());
    1505           8 :         nsCOMPtr<nsPIDOMWindowOuter> opener = do_QueryInterface(slots->mFrameLoaderOrOpener);
    1506           4 :         if (!opener) {
    1507             :             // If we are a primary xul-browser, we want to take the opener property!
    1508           8 :             nsCOMPtr<nsIDOMChromeWindow> chromeWindow = do_QueryInterface(OwnerDoc()->GetWindow());
    1509           8 :             if (AttrValueIs(kNameSpaceID_None, nsGkAtoms::primary,
    1510           7 :                             nsGkAtoms::_true, eIgnoreCase) &&
    1511           3 :                 chromeWindow) {
    1512           4 :                 nsCOMPtr<mozIDOMWindowProxy> wp;
    1513           2 :                 chromeWindow->TakeOpenerForInitialContentBrowser(getter_AddRefs(wp));
    1514           2 :                 opener = nsPIDOMWindowOuter::From(wp);
    1515             :             }
    1516             :         }
    1517             : 
    1518             :         // false as the last parameter so that xul:iframe/browser/editor
    1519             :         // session history handling works like dynamic html:iframes.
    1520             :         // Usually xul elements are used in chrome, which doesn't have
    1521             :         // session history at all.
    1522           4 :         frameLoader = nsFrameLoader::Create(this, opener, false);
    1523           4 :         slots->mFrameLoaderOrOpener = static_cast<nsIFrameLoader*>(frameLoader);
    1524           4 :         NS_ENSURE_TRUE(frameLoader, NS_OK);
    1525             : 
    1526             :         (new AsyncEventDispatcher(this,
    1527           8 :                                   NS_LITERAL_STRING("XULFrameLoaderCreated"),
    1528           8 :                                   /* aBubbles */ true))->RunDOMEventWhenSafe();
    1529             : 
    1530           8 :         if (AttrValueIs(kNameSpaceID_None, nsGkAtoms::prerendered,
    1531           8 :                         NS_LITERAL_STRING("true"), eIgnoreCase)) {
    1532           0 :             nsresult rv = frameLoader->SetIsPrerendered();
    1533           0 :             NS_ENSURE_SUCCESS(rv,rv);
    1534             :         }
    1535             :     }
    1536             : 
    1537           4 :     return frameLoader->LoadFrame();
    1538             : }
    1539             : 
    1540             : nsresult
    1541           0 : nsXULElement::GetFrameLoaderXPCOM(nsIFrameLoader **aFrameLoader)
    1542             : {
    1543           0 :     *aFrameLoader = GetFrameLoader().take();
    1544           0 :     return NS_OK;
    1545             : }
    1546             : 
    1547             : already_AddRefed<nsFrameLoader>
    1548         214 : nsXULElement::GetFrameLoader()
    1549             : {
    1550         214 :     nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingSlots());
    1551         214 :     if (!slots)
    1552           3 :         return nullptr;
    1553             : 
    1554         422 :     nsCOMPtr<nsIFrameLoader> loader = do_QueryInterface(slots->mFrameLoaderOrOpener);
    1555         211 :     return already_AddRefed<nsFrameLoader>(static_cast<nsFrameLoader*>(loader.forget().take()));
    1556             : }
    1557             : 
    1558             : void
    1559           0 : nsXULElement::PresetOpenerWindow(mozIDOMWindowProxy* aWindow, ErrorResult& aRv)
    1560             : {
    1561           0 :     nsXULSlots* slots = static_cast<nsXULSlots*>(Slots());
    1562           0 :     MOZ_ASSERT(!slots->mFrameLoaderOrOpener, "A frameLoader or opener is present when calling PresetOpenerWindow");
    1563             : 
    1564           0 :     slots->mFrameLoaderOrOpener = aWindow;
    1565           0 : }
    1566             : 
    1567             : nsresult
    1568           0 : nsXULElement::SetIsPrerendered()
    1569             : {
    1570           0 :   return SetAttr(kNameSpaceID_None, nsGkAtoms::prerendered, nullptr,
    1571           0 :                  NS_LITERAL_STRING("true"), true);
    1572             : }
    1573             : 
    1574             : void
    1575           0 : nsXULElement::InternalSetFrameLoader(nsIFrameLoader* aNewFrameLoader)
    1576             : {
    1577           0 :     nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingDOMSlots());
    1578           0 :     MOZ_ASSERT(slots);
    1579             : 
    1580           0 :     slots->mFrameLoaderOrOpener = aNewFrameLoader;
    1581           0 : }
    1582             : 
    1583             : void
    1584           0 : nsXULElement::SwapFrameLoaders(HTMLIFrameElement& aOtherLoaderOwner,
    1585             :                                ErrorResult& rv)
    1586             : {
    1587           0 :     if (!GetExistingDOMSlots()) {
    1588           0 :         rv.Throw(NS_ERROR_NOT_IMPLEMENTED);
    1589           0 :         return;
    1590             :     }
    1591             : 
    1592           0 :     nsCOMPtr<nsIFrameLoaderOwner> flo = do_QueryInterface(static_cast<nsIDOMXULElement*>(this));
    1593           0 :     aOtherLoaderOwner.SwapFrameLoaders(flo, rv);
    1594             : }
    1595             : 
    1596             : void
    1597           0 : nsXULElement::SwapFrameLoaders(nsXULElement& aOtherLoaderOwner,
    1598             :                                ErrorResult& rv)
    1599             : {
    1600           0 :     if (&aOtherLoaderOwner == this) {
    1601             :         // nothing to do
    1602           0 :         return;
    1603             :     }
    1604             : 
    1605           0 :     if (!GetExistingDOMSlots()) {
    1606           0 :         rv.Throw(NS_ERROR_NOT_IMPLEMENTED);
    1607           0 :         return;
    1608             :     }
    1609             : 
    1610           0 :     nsCOMPtr<nsIFrameLoaderOwner> flo = do_QueryInterface(static_cast<nsIDOMXULElement*>(this));
    1611           0 :     aOtherLoaderOwner.SwapFrameLoaders(flo, rv);
    1612             : }
    1613             : 
    1614             : void
    1615           0 : nsXULElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherLoaderOwner,
    1616             :                                mozilla::ErrorResult& rv)
    1617             : {
    1618           0 :     if (!GetExistingDOMSlots()) {
    1619           0 :         rv.Throw(NS_ERROR_NOT_IMPLEMENTED);
    1620           0 :         return;
    1621             :     }
    1622             : 
    1623           0 :     RefPtr<nsFrameLoader> loader = GetFrameLoader();
    1624           0 :     RefPtr<nsFrameLoader> otherLoader = aOtherLoaderOwner->GetFrameLoader();
    1625           0 :     if (!loader || !otherLoader) {
    1626           0 :         rv.Throw(NS_ERROR_NOT_IMPLEMENTED);
    1627           0 :         return;
    1628             :     }
    1629             : 
    1630           0 :     nsCOMPtr<nsIFrameLoaderOwner> flo = do_QueryInterface(static_cast<nsIDOMXULElement*>(this));
    1631           0 :     rv = loader->SwapWithOtherLoader(otherLoader, flo, aOtherLoaderOwner);
    1632             : }
    1633             : 
    1634             : NS_IMETHODIMP
    1635           0 : nsXULElement::GetParentTree(nsIDOMXULMultiSelectControlElement** aTreeElement)
    1636             : {
    1637           0 :     for (nsIContent* current = GetParent(); current;
    1638           0 :          current = current->GetParent()) {
    1639           0 :         if (current->NodeInfo()->Equals(nsGkAtoms::listbox,
    1640             :                                         kNameSpaceID_XUL)) {
    1641           0 :             CallQueryInterface(current, aTreeElement);
    1642             :             // XXX returning NS_OK because that's what the code used to do;
    1643             :             // is that the right thing, though?
    1644             : 
    1645           0 :             return NS_OK;
    1646             :         }
    1647             :     }
    1648             : 
    1649           0 :     return NS_OK;
    1650             : }
    1651             : 
    1652             : void
    1653           0 : nsXULElement::Click(CallerType aCallerType)
    1654             : {
    1655           0 :   ClickWithInputSource(nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN,
    1656           0 :                        aCallerType == CallerType::System);
    1657           0 : }
    1658             : 
    1659             : void
    1660           0 : nsXULElement::ClickWithInputSource(uint16_t aInputSource, bool aIsTrustedEvent)
    1661             : {
    1662           0 :     if (BoolAttrIsTrue(nsGkAtoms::disabled))
    1663           0 :         return;
    1664             : 
    1665           0 :     nsCOMPtr<nsIDocument> doc = GetComposedDoc(); // Strong just in case
    1666           0 :     if (doc) {
    1667           0 :         nsCOMPtr<nsIPresShell> shell = doc->GetShell();
    1668           0 :         if (shell) {
    1669             :             // strong ref to PresContext so events don't destroy it
    1670           0 :             RefPtr<nsPresContext> context = shell->GetPresContext();
    1671             : 
    1672             :             WidgetMouseEvent eventDown(aIsTrustedEvent, eMouseDown,
    1673           0 :                                        nullptr, WidgetMouseEvent::eReal);
    1674             :             WidgetMouseEvent eventUp(aIsTrustedEvent, eMouseUp,
    1675           0 :                                      nullptr, WidgetMouseEvent::eReal);
    1676             :             WidgetMouseEvent eventClick(aIsTrustedEvent, eMouseClick, nullptr,
    1677           0 :                                         WidgetMouseEvent::eReal);
    1678           0 :             eventDown.inputSource = eventUp.inputSource = eventClick.inputSource
    1679           0 :                                   = aInputSource;
    1680             : 
    1681             :             // send mouse down
    1682           0 :             nsEventStatus status = nsEventStatus_eIgnore;
    1683           0 :             EventDispatcher::Dispatch(static_cast<nsIContent*>(this),
    1684           0 :                                       context, &eventDown,  nullptr, &status);
    1685             : 
    1686             :             // send mouse up
    1687           0 :             status = nsEventStatus_eIgnore;  // reset status
    1688           0 :             EventDispatcher::Dispatch(static_cast<nsIContent*>(this),
    1689           0 :                                       context, &eventUp, nullptr, &status);
    1690             : 
    1691             :             // send mouse click
    1692           0 :             status = nsEventStatus_eIgnore;  // reset status
    1693           0 :             EventDispatcher::Dispatch(static_cast<nsIContent*>(this),
    1694           0 :                                       context, &eventClick, nullptr, &status);
    1695             : 
    1696             :             // If the click has been prevented, lets skip the command call
    1697             :             // this is how a physical click works
    1698           0 :             if (status == nsEventStatus_eConsumeNoDefault) {
    1699           0 :                 return;
    1700             :             }
    1701             :         }
    1702             :     }
    1703             : 
    1704             :     // oncommand is fired when an element is clicked...
    1705           0 :     DoCommand();
    1706             : }
    1707             : 
    1708             : void
    1709           0 : nsXULElement::DoCommand()
    1710             : {
    1711           0 :     nsCOMPtr<nsIDocument> doc = GetComposedDoc(); // strong just in case
    1712           0 :     if (doc) {
    1713           0 :         nsContentUtils::DispatchXULCommand(this, true);
    1714             :     }
    1715           0 : }
    1716             : 
    1717             : nsIContent *
    1718      223709 : nsXULElement::GetBindingParent() const
    1719             : {
    1720      223709 :     return mBindingParent;
    1721             : }
    1722             : 
    1723             : bool
    1724      150780 : nsXULElement::IsNodeOfType(uint32_t aFlags) const
    1725             : {
    1726      150780 :     return !(aFlags & ~eCONTENT);
    1727             : }
    1728             : 
    1729             : nsresult
    1730          25 : nsXULElement::AddPopupListener(nsIAtom* aName)
    1731             : {
    1732             :     // Add a popup listener to the element
    1733          26 :     bool isContext = (aName == nsGkAtoms::context ||
    1734          26 :                         aName == nsGkAtoms::contextmenu);
    1735          25 :     uint32_t listenerFlag = isContext ?
    1736             :                             XUL_ELEMENT_HAS_CONTENTMENU_LISTENER :
    1737          25 :                             XUL_ELEMENT_HAS_POPUP_LISTENER;
    1738             : 
    1739          25 :     if (HasFlag(listenerFlag)) {
    1740           0 :         return NS_OK;
    1741             :     }
    1742             : 
    1743             :     nsCOMPtr<nsIDOMEventListener> listener =
    1744          50 :       new nsXULPopupListener(this, isContext);
    1745             : 
    1746             :     // Add the popup as a listener on this element.
    1747          25 :     EventListenerManager* manager = GetOrCreateListenerManager();
    1748          25 :     SetFlags(listenerFlag);
    1749             : 
    1750          25 :     if (isContext) {
    1751          25 :       manager->AddEventListenerByType(listener,
    1752          50 :                                       NS_LITERAL_STRING("contextmenu"),
    1753         100 :                                       TrustedEventsAtSystemGroupBubble());
    1754             :     } else {
    1755           0 :       manager->AddEventListenerByType(listener,
    1756           0 :                                       NS_LITERAL_STRING("mousedown"),
    1757           0 :                                       TrustedEventsAtSystemGroupBubble());
    1758             :     }
    1759          25 :     return NS_OK;
    1760             : }
    1761             : 
    1762             : EventStates
    1763        4746 : nsXULElement::IntrinsicState() const
    1764             : {
    1765        4746 :     EventStates state = nsStyledElement::IntrinsicState();
    1766             : 
    1767        4746 :     if (IsReadWriteTextElement()) {
    1768          13 :         state |= NS_EVENT_STATE_MOZ_READWRITE;
    1769          13 :         state &= ~NS_EVENT_STATE_MOZ_READONLY;
    1770             :     }
    1771             : 
    1772        4746 :     return state;
    1773             : }
    1774             : 
    1775             : //----------------------------------------------------------------------
    1776             : 
    1777             : nsresult
    1778        1667 : nsXULElement::MakeHeavyweight(nsXULPrototypeElement* aPrototype)
    1779             : {
    1780        1667 :     if (!aPrototype) {
    1781           0 :         return NS_OK;
    1782             :     }
    1783             : 
    1784             :     uint32_t i;
    1785             :     nsresult rv;
    1786        6689 :     for (i = 0; i < aPrototype->mNumAttributes; ++i) {
    1787        5022 :         nsXULPrototypeAttribute* protoattr = &aPrototype->mAttributes[i];
    1788       10044 :         nsAttrValue attrValue;
    1789             : 
    1790             :         // Style rules need to be cloned.
    1791        5022 :         if (protoattr->mValue.Type() == nsAttrValue::eCSSDeclaration) {
    1792           7 :             DeclarationBlock* decl = protoattr->mValue.GetCSSDeclarationValue();
    1793          14 :             RefPtr<DeclarationBlock> declClone = decl->Clone();
    1794             : 
    1795          14 :             nsString stringValue;
    1796           7 :             protoattr->mValue.ToString(stringValue);
    1797             : 
    1798           7 :             attrValue.SetTo(declClone.forget(), &stringValue);
    1799             :         } else {
    1800        5015 :             attrValue.SetTo(protoattr->mValue);
    1801             :         }
    1802             : 
    1803             :         bool oldValueSet;
    1804             :         // XXX we might wanna have a SetAndTakeAttr that takes an nsAttrName
    1805        5022 :         if (protoattr->mName.IsAtom()) {
    1806        4807 :             rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.Atom(),
    1807        4807 :                                                   attrValue, &oldValueSet);
    1808             :         } else {
    1809         215 :             rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.NodeInfo(),
    1810         215 :                                                   attrValue, &oldValueSet);
    1811             :         }
    1812        5022 :         NS_ENSURE_SUCCESS(rv, rv);
    1813             :     }
    1814        1667 :     return NS_OK;
    1815             : }
    1816             : 
    1817             : nsresult
    1818           0 : nsXULElement::HideWindowChrome(bool aShouldHide)
    1819             : {
    1820           0 :     nsIDocument* doc = GetUncomposedDoc();
    1821           0 :     if (!doc || doc->GetRootElement() != this)
    1822           0 :       return NS_ERROR_UNEXPECTED;
    1823             : 
    1824             :     // only top level chrome documents can hide the window chrome
    1825           0 :     if (!doc->IsRootDisplayDocument())
    1826           0 :       return NS_OK;
    1827             : 
    1828           0 :     nsIPresShell *shell = doc->GetShell();
    1829             : 
    1830           0 :     if (shell) {
    1831           0 :         nsIFrame* frame = GetPrimaryFrame();
    1832             : 
    1833           0 :         nsPresContext *presContext = shell->GetPresContext();
    1834             : 
    1835           0 :         if (frame && presContext && presContext->IsChrome()) {
    1836           0 :             nsView* view = frame->GetClosestView();
    1837             : 
    1838           0 :             if (view) {
    1839           0 :                 nsIWidget* w = view->GetWidget();
    1840           0 :                 NS_ENSURE_STATE(w);
    1841           0 :                 w->HideWindowChrome(aShouldHide);
    1842             :             }
    1843             :         }
    1844             :     }
    1845             : 
    1846           0 :     return NS_OK;
    1847             : }
    1848             : 
    1849             : nsIWidget*
    1850           0 : nsXULElement::GetWindowWidget()
    1851             : {
    1852           0 :     nsIDocument* doc = GetComposedDoc();
    1853             : 
    1854             :     // only top level chrome documents can set the titlebar color
    1855           0 :     if (doc && doc->IsRootDisplayDocument()) {
    1856           0 :         nsCOMPtr<nsISupports> container = doc->GetContainer();
    1857           0 :         nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(container);
    1858           0 :         if (baseWindow) {
    1859           0 :             nsCOMPtr<nsIWidget> mainWidget;
    1860           0 :             baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
    1861           0 :             return mainWidget;
    1862             :         }
    1863             :     }
    1864           0 :     return nullptr;
    1865             : }
    1866             : 
    1867             : void
    1868           0 : nsXULElement::SetTitlebarColor(nscolor aColor, bool aActive)
    1869             : {
    1870           0 :     nsIWidget* mainWidget = GetWindowWidget();
    1871           0 :     if (mainWidget) {
    1872           0 :         mainWidget->SetWindowTitlebarColor(aColor, aActive);
    1873             :     }
    1874           0 : }
    1875             : 
    1876           0 : class SetDrawInTitleBarEvent : public Runnable
    1877             : {
    1878             : public:
    1879           0 :   SetDrawInTitleBarEvent(nsIWidget* aWidget, bool aState)
    1880           0 :     : mozilla::Runnable("SetDrawInTitleBarEvent")
    1881             :     , mWidget(aWidget)
    1882           0 :     , mState(aState)
    1883           0 :   {}
    1884             : 
    1885           0 :   NS_IMETHOD Run() override {
    1886           0 :     NS_ASSERTION(mWidget, "You shouldn't call this runnable with a null widget!");
    1887             : 
    1888           0 :     mWidget->SetDrawsInTitlebar(mState);
    1889           0 :     return NS_OK;
    1890             :   }
    1891             : 
    1892             : private:
    1893             :   nsCOMPtr<nsIWidget> mWidget;
    1894             :   bool mState;
    1895             : };
    1896             : 
    1897             : void
    1898           0 : nsXULElement::SetDrawsInTitlebar(bool aState)
    1899             : {
    1900           0 :     nsIWidget* mainWidget = GetWindowWidget();
    1901           0 :     if (mainWidget) {
    1902           0 :         nsContentUtils::AddScriptRunner(new SetDrawInTitleBarEvent(mainWidget, aState));
    1903             :     }
    1904           0 : }
    1905             : 
    1906             : void
    1907           0 : nsXULElement::SetDrawsTitle(bool aState)
    1908             : {
    1909           0 :     nsIWidget* mainWidget = GetWindowWidget();
    1910           0 :     if (mainWidget) {
    1911             :         // We can do this synchronously because SetDrawsTitle doesn't have any
    1912             :         // synchronous effects apart from a harmless invalidation.
    1913           0 :         mainWidget->SetDrawsTitle(aState);
    1914             :     }
    1915           0 : }
    1916             : 
    1917             : void
    1918           0 : nsXULElement::UpdateBrightTitlebarForeground(nsIDocument* aDoc)
    1919             : {
    1920           0 :     nsIWidget* mainWidget = GetWindowWidget();
    1921           0 :     if (mainWidget) {
    1922             :         // We can do this synchronously because SetBrightTitlebarForeground doesn't have any
    1923             :         // synchronous effects apart from a harmless invalidation.
    1924           0 :         mainWidget->SetUseBrightTitlebarForeground(
    1925           0 :           aDoc->GetDocumentLWTheme() == nsIDocument::Doc_Theme_Bright ||
    1926           0 :           aDoc->GetRootElement()->AttrValueIs(kNameSpaceID_None,
    1927             :                                               nsGkAtoms::brighttitlebarforeground,
    1928           0 :                                               NS_LITERAL_STRING("true"),
    1929           0 :                                               eCaseMatters));
    1930             :     }
    1931           0 : }
    1932             : 
    1933           0 : class MarginSetter : public Runnable
    1934             : {
    1935             : public:
    1936           0 :   explicit MarginSetter(nsIWidget* aWidget)
    1937           0 :     : mozilla::Runnable("MarginSetter")
    1938             :     , mWidget(aWidget)
    1939           0 :     , mMargin(-1, -1, -1, -1)
    1940             :   {
    1941           0 :   }
    1942           0 :   MarginSetter(nsIWidget* aWidget, const LayoutDeviceIntMargin& aMargin)
    1943           0 :     : mozilla::Runnable("MarginSetter")
    1944             :     , mWidget(aWidget)
    1945           0 :     , mMargin(aMargin)
    1946             :   {
    1947           0 :   }
    1948             : 
    1949           0 :   NS_IMETHOD Run() override
    1950             :   {
    1951             :     // SetNonClientMargins can dispatch native events, hence doing
    1952             :     // it off a script runner.
    1953           0 :     mWidget->SetNonClientMargins(mMargin);
    1954           0 :     return NS_OK;
    1955             :     }
    1956             : 
    1957             : private:
    1958             :     nsCOMPtr<nsIWidget> mWidget;
    1959             :     LayoutDeviceIntMargin mMargin;
    1960             : };
    1961             : 
    1962             : void
    1963           0 : nsXULElement::SetChromeMargins(const nsAttrValue* aValue)
    1964             : {
    1965           0 :     if (!aValue)
    1966           0 :         return;
    1967             : 
    1968           0 :     nsIWidget* mainWidget = GetWindowWidget();
    1969           0 :     if (!mainWidget)
    1970           0 :         return;
    1971             : 
    1972             :     // top, right, bottom, left - see nsAttrValue
    1973           0 :     nsIntMargin margins;
    1974           0 :     bool gotMargins = false;
    1975             : 
    1976           0 :     if (aValue->Type() == nsAttrValue::eIntMarginValue) {
    1977           0 :         gotMargins = aValue->GetIntMarginValue(margins);
    1978             :     } else {
    1979           0 :         nsAutoString tmp;
    1980           0 :         aValue->ToString(tmp);
    1981           0 :         gotMargins = nsContentUtils::ParseIntMarginValue(tmp, margins);
    1982             :     }
    1983           0 :     if (gotMargins) {
    1984           0 :         nsContentUtils::AddScriptRunner(
    1985             :             new MarginSetter(
    1986           0 :                 mainWidget, LayoutDeviceIntMargin::FromUnknownMargin(margins)));
    1987             :     }
    1988             : }
    1989             : 
    1990             : void
    1991           0 : nsXULElement::ResetChromeMargins()
    1992             : {
    1993           0 :     nsIWidget* mainWidget = GetWindowWidget();
    1994           0 :     if (!mainWidget)
    1995           0 :         return;
    1996             :     // See nsIWidget
    1997           0 :     nsContentUtils::AddScriptRunner(new MarginSetter(mainWidget));
    1998             : }
    1999             : 
    2000             : bool
    2001           7 : nsXULElement::BoolAttrIsTrue(nsIAtom* aName) const
    2002             : {
    2003             :     const nsAttrValue* attr =
    2004           7 :         GetAttrInfo(kNameSpaceID_None, aName).mValue;
    2005             : 
    2006          12 :     return attr && attr->Type() == nsAttrValue::eAtom &&
    2007          12 :            attr->GetAtomValue() == nsGkAtoms::_true;
    2008             : }
    2009             : 
    2010             : void
    2011           0 : nsXULElement::RecompileScriptEventListeners()
    2012             : {
    2013           0 :     int32_t i, count = mAttrsAndChildren.AttrCount();
    2014           0 :     for (i = 0; i < count; ++i) {
    2015           0 :         const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
    2016             : 
    2017             :         // Eventlistenener-attributes are always in the null namespace
    2018           0 :         if (!name->IsAtom()) {
    2019           0 :             continue;
    2020             :         }
    2021             : 
    2022           0 :         nsIAtom *attr = name->Atom();
    2023           0 :         if (!nsContentUtils::IsEventAttributeName(attr, EventNameType_XUL)) {
    2024           0 :             continue;
    2025             :         }
    2026             : 
    2027           0 :         nsAutoString value;
    2028           0 :         GetAttr(kNameSpaceID_None, attr, value);
    2029           0 :         SetEventHandler(attr, value, true);
    2030             :     }
    2031           0 : }
    2032             : 
    2033             : bool
    2034           0 : nsXULElement::IsEventAttributeNameInternal(nsIAtom *aName)
    2035             : {
    2036           0 :   return nsContentUtils::IsEventAttributeName(aName, EventNameType_XUL);
    2037             : }
    2038             : 
    2039             : JSObject*
    2040         384 : nsXULElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
    2041             : {
    2042         384 :     return dom::XULElementBinding::Wrap(aCx, this, aGivenProto);
    2043             : }
    2044             : 
    2045             : NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPrototypeNode)
    2046             : 
    2047           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULPrototypeNode)
    2048           0 :     if (tmp->mType == nsXULPrototypeNode::eType_Element) {
    2049           0 :         static_cast<nsXULPrototypeElement*>(tmp)->Unlink();
    2050           0 :     } else if (tmp->mType == nsXULPrototypeNode::eType_Script) {
    2051           0 :         static_cast<nsXULPrototypeScript*>(tmp)->UnlinkJSObjects();
    2052             :     }
    2053           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    2054           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULPrototypeNode)
    2055           0 :     if (tmp->mType == nsXULPrototypeNode::eType_Element) {
    2056             :         nsXULPrototypeElement *elem =
    2057           0 :             static_cast<nsXULPrototypeElement*>(tmp);
    2058           0 :         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mNodeInfo");
    2059           0 :         cb.NoteNativeChild(elem->mNodeInfo,
    2060           0 :                            NS_CYCLE_COLLECTION_PARTICIPANT(NodeInfo));
    2061             :         uint32_t i;
    2062           0 :         for (i = 0; i < elem->mNumAttributes; ++i) {
    2063           0 :             const nsAttrName& name = elem->mAttributes[i].mName;
    2064           0 :             if (!name.IsAtom()) {
    2065             :                 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
    2066           0 :                     "mAttributes[i].mName.NodeInfo()");
    2067           0 :                 cb.NoteNativeChild(name.NodeInfo(),
    2068           0 :                                    NS_CYCLE_COLLECTION_PARTICIPANT(NodeInfo));
    2069             :             }
    2070             :         }
    2071           0 :         ImplCycleCollectionTraverse(cb, elem->mChildren, "mChildren");
    2072             :     }
    2073           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    2074         432 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXULPrototypeNode)
    2075         432 :     if (tmp->mType == nsXULPrototypeNode::eType_Script) {
    2076             :         nsXULPrototypeScript *script =
    2077          39 :             static_cast<nsXULPrototypeScript*>(tmp);
    2078          39 :         script->Trace(aCallbacks, aClosure);
    2079             :     }
    2080         432 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
    2081             : 
    2082           0 : NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsXULPrototypeNode, AddRef)
    2083           0 : NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsXULPrototypeNode, Release)
    2084             : 
    2085             : //----------------------------------------------------------------------
    2086             : //
    2087             : // nsXULPrototypeAttribute
    2088             : //
    2089             : 
    2090        2220 : nsXULPrototypeAttribute::~nsXULPrototypeAttribute()
    2091             : {
    2092        1110 :     MOZ_COUNT_DTOR(nsXULPrototypeAttribute);
    2093        1110 : }
    2094             : 
    2095             : 
    2096             : //----------------------------------------------------------------------
    2097             : //
    2098             : // nsXULPrototypeElement
    2099             : //
    2100             : 
    2101             : nsresult
    2102           0 : nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream,
    2103             :                                  nsXULPrototypeDocument* aProtoDoc,
    2104             :                                  const nsTArray<RefPtr<mozilla::dom::NodeInfo>> *aNodeInfos)
    2105             : {
    2106             :     nsresult rv;
    2107             : 
    2108             :     // Write basic prototype data
    2109           0 :     rv = aStream->Write32(mType);
    2110             : 
    2111             :     // Write Node Info
    2112           0 :     int32_t index = aNodeInfos->IndexOf(mNodeInfo);
    2113           0 :     NS_ASSERTION(index >= 0, "unknown mozilla::dom::NodeInfo index");
    2114           0 :     nsresult tmp = aStream->Write32(index);
    2115           0 :     if (NS_FAILED(tmp)) {
    2116           0 :       rv = tmp;
    2117             :     }
    2118             : 
    2119             :     // Write Attributes
    2120           0 :     tmp = aStream->Write32(mNumAttributes);
    2121           0 :     if (NS_FAILED(tmp)) {
    2122           0 :       rv = tmp;
    2123             :     }
    2124             : 
    2125           0 :     nsAutoString attributeValue;
    2126             :     uint32_t i;
    2127           0 :     for (i = 0; i < mNumAttributes; ++i) {
    2128           0 :         RefPtr<mozilla::dom::NodeInfo> ni;
    2129           0 :         if (mAttributes[i].mName.IsAtom()) {
    2130             :             ni = mNodeInfo->NodeInfoManager()->
    2131           0 :                 GetNodeInfo(mAttributes[i].mName.Atom(), nullptr,
    2132             :                             kNameSpaceID_None,
    2133           0 :                             nsIDOMNode::ATTRIBUTE_NODE);
    2134           0 :             NS_ASSERTION(ni, "the nodeinfo should already exist");
    2135             :         } else {
    2136           0 :             ni = mAttributes[i].mName.NodeInfo();
    2137             :         }
    2138             : 
    2139           0 :         index = aNodeInfos->IndexOf(ni);
    2140           0 :         NS_ASSERTION(index >= 0, "unknown mozilla::dom::NodeInfo index");
    2141           0 :         tmp = aStream->Write32(index);
    2142           0 :         if (NS_FAILED(tmp)) {
    2143           0 :           rv = tmp;
    2144             :         }
    2145             : 
    2146           0 :         mAttributes[i].mValue.ToString(attributeValue);
    2147           0 :         tmp = aStream->WriteWStringZ(attributeValue.get());
    2148           0 :         if (NS_FAILED(tmp)) {
    2149           0 :           rv = tmp;
    2150             :         }
    2151             :     }
    2152             : 
    2153             :     // Now write children
    2154           0 :     tmp = aStream->Write32(uint32_t(mChildren.Length()));
    2155           0 :     if (NS_FAILED(tmp)) {
    2156           0 :       rv = tmp;
    2157             :     }
    2158           0 :     for (i = 0; i < mChildren.Length(); i++) {
    2159           0 :         nsXULPrototypeNode* child = mChildren[i].get();
    2160           0 :         switch (child->mType) {
    2161             :         case eType_Element:
    2162             :         case eType_Text:
    2163             :         case eType_PI:
    2164           0 :             tmp = child->Serialize(aStream, aProtoDoc, aNodeInfos);
    2165           0 :             if (NS_FAILED(tmp)) {
    2166           0 :               rv = tmp;
    2167             :             }
    2168           0 :             break;
    2169             :         case eType_Script:
    2170           0 :             tmp = aStream->Write32(child->mType);
    2171           0 :             if (NS_FAILED(tmp)) {
    2172           0 :               rv = tmp;
    2173             :             }
    2174           0 :             nsXULPrototypeScript* script = static_cast<nsXULPrototypeScript*>(child);
    2175             : 
    2176           0 :             tmp = aStream->Write8(script->mOutOfLine);
    2177           0 :             if (NS_FAILED(tmp)) {
    2178           0 :               rv = tmp;
    2179             :             }
    2180           0 :             if (! script->mOutOfLine) {
    2181           0 :                 tmp = script->Serialize(aStream, aProtoDoc, aNodeInfos);
    2182           0 :                 if (NS_FAILED(tmp)) {
    2183           0 :                   rv = tmp;
    2184             :                 }
    2185             :             } else {
    2186             :                 tmp = aStream->WriteCompoundObject(script->mSrcURI,
    2187             :                                                    NS_GET_IID(nsIURI),
    2188           0 :                                                    true);
    2189           0 :                 if (NS_FAILED(tmp)) {
    2190           0 :                   rv = tmp;
    2191             :                 }
    2192             : 
    2193           0 :                 if (script->HasScriptObject()) {
    2194             :                     // This may return NS_OK without muxing script->mSrcURI's
    2195             :                     // data into the cache file, in the case where that
    2196             :                     // muxed document is already there (written by a prior
    2197             :                     // session, or by an earlier cache episode during this
    2198             :                     // session).
    2199           0 :                     tmp = script->SerializeOutOfLine(aStream, aProtoDoc);
    2200           0 :                     if (NS_FAILED(tmp)) {
    2201           0 :                       rv = tmp;
    2202             :                     }
    2203             :                 }
    2204             :             }
    2205           0 :             break;
    2206             :         }
    2207             :     }
    2208             : 
    2209           0 :     return rv;
    2210             : }
    2211             : 
    2212             : nsresult
    2213        1297 : nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream,
    2214             :                                    nsXULPrototypeDocument* aProtoDoc,
    2215             :                                    nsIURI* aDocumentURI,
    2216             :                                    const nsTArray<RefPtr<mozilla::dom::NodeInfo>> *aNodeInfos)
    2217             : {
    2218        1297 :     NS_PRECONDITION(aNodeInfos, "missing nodeinfo array");
    2219             : 
    2220             :     // Read Node Info
    2221        1297 :     uint32_t number = 0;
    2222        1297 :     nsresult rv = aStream->Read32(&number);
    2223        1297 :     if (NS_WARN_IF(NS_FAILED(rv))) return rv;
    2224        1297 :     mNodeInfo = aNodeInfos->SafeElementAt(number, nullptr);
    2225        1297 :     if (!mNodeInfo) {
    2226           0 :         return NS_ERROR_UNEXPECTED;
    2227             :     }
    2228             : 
    2229             :     // Read Attributes
    2230        1297 :     rv = aStream->Read32(&number);
    2231        1297 :     if (NS_WARN_IF(NS_FAILED(rv))) return rv;
    2232        1297 :     mNumAttributes = int32_t(number);
    2233             : 
    2234        1297 :     if (mNumAttributes > 0) {
    2235        2460 :         mAttributes = new (fallible) nsXULPrototypeAttribute[mNumAttributes];
    2236        1230 :         if (!mAttributes) {
    2237           0 :             return NS_ERROR_OUT_OF_MEMORY;
    2238             :         }
    2239             : 
    2240        2460 :         nsAutoString attributeValue;
    2241        5168 :         for (uint32_t i = 0; i < mNumAttributes; ++i) {
    2242        3938 :             rv = aStream->Read32(&number);
    2243        3938 :             if (NS_WARN_IF(NS_FAILED(rv))) return rv;
    2244        3938 :             mozilla::dom::NodeInfo* ni = aNodeInfos->SafeElementAt(number, nullptr);
    2245        3938 :             if (!ni) {
    2246           0 :                 return NS_ERROR_UNEXPECTED;
    2247             :             }
    2248             : 
    2249        3938 :             mAttributes[i].mName.SetTo(ni);
    2250             : 
    2251        3938 :             rv = aStream->ReadString(attributeValue);
    2252        3938 :             if (NS_WARN_IF(NS_FAILED(rv))) return rv;
    2253        3938 :             rv = SetAttrAt(i, attributeValue, aDocumentURI);
    2254        3938 :             if (NS_WARN_IF(NS_FAILED(rv))) return rv;
    2255             :         }
    2256             :     }
    2257             : 
    2258        1297 :     rv = aStream->Read32(&number);
    2259        1297 :     if (NS_WARN_IF(NS_FAILED(rv))) return rv;
    2260        1297 :     uint32_t numChildren = int32_t(number);
    2261             : 
    2262        1297 :     if (numChildren > 0) {
    2263         371 :         if (!mChildren.SetCapacity(numChildren, fallible)) {
    2264           0 :             return NS_ERROR_OUT_OF_MEMORY;
    2265             :         }
    2266             : 
    2267        1787 :         for (uint32_t i = 0; i < numChildren; i++) {
    2268        1416 :             rv = aStream->Read32(&number);
    2269        1416 :             if (NS_WARN_IF(NS_FAILED(rv))) return rv;
    2270        1416 :             Type childType = (Type)number;
    2271             : 
    2272        2832 :             RefPtr<nsXULPrototypeNode> child;
    2273             : 
    2274        1416 :             switch (childType) {
    2275             :             case eType_Element:
    2276        1291 :                 child = new nsXULPrototypeElement();
    2277        1291 :                 rv = child->Deserialize(aStream, aProtoDoc, aDocumentURI,
    2278        1291 :                                         aNodeInfos);
    2279        1291 :                 if (NS_WARN_IF(NS_FAILED(rv))) return rv;
    2280        1291 :                 break;
    2281             :             case eType_Text:
    2282          86 :                 child = new nsXULPrototypeText();
    2283          86 :                 rv = child->Deserialize(aStream, aProtoDoc, aDocumentURI,
    2284          86 :                                         aNodeInfos);
    2285          86 :                 if (NS_WARN_IF(NS_FAILED(rv))) return rv;
    2286          86 :                 break;
    2287             :             case eType_PI:
    2288           0 :                 child = new nsXULPrototypePI();
    2289           0 :                 rv = child->Deserialize(aStream, aProtoDoc, aDocumentURI,
    2290           0 :                                         aNodeInfos);
    2291           0 :                 if (NS_WARN_IF(NS_FAILED(rv))) return rv;
    2292           0 :                 break;
    2293             :             case eType_Script: {
    2294             :                 // language version/options obtained during deserialization.
    2295          39 :                 RefPtr<nsXULPrototypeScript> script = new nsXULPrototypeScript(0, 0);
    2296             : 
    2297          39 :                 rv = aStream->ReadBoolean(&script->mOutOfLine);
    2298          39 :                 if (NS_WARN_IF(NS_FAILED(rv))) return rv;
    2299          39 :                 if (!script->mOutOfLine) {
    2300           1 :                     rv = script->Deserialize(aStream, aProtoDoc, aDocumentURI,
    2301           1 :                                              aNodeInfos);
    2302           1 :                     if (NS_WARN_IF(NS_FAILED(rv))) return rv;
    2303             :                 } else {
    2304          76 :                     nsCOMPtr<nsISupports> supports;
    2305          38 :                     rv = aStream->ReadObject(true, getter_AddRefs(supports));
    2306          38 :                     if (NS_WARN_IF(NS_FAILED(rv))) return rv;
    2307          38 :                     script->mSrcURI = do_QueryInterface(supports);
    2308             : 
    2309          38 :                     rv = script->DeserializeOutOfLine(aStream, aProtoDoc);
    2310          38 :                     if (NS_WARN_IF(NS_FAILED(rv))) return rv;
    2311             :                 }
    2312             : 
    2313          39 :                 child = script.forget();
    2314          39 :                 break;
    2315             :             }
    2316             :             default:
    2317           0 :                 MOZ_ASSERT(false, "Unexpected child type!");
    2318             :                 return NS_ERROR_UNEXPECTED;
    2319             :             }
    2320             : 
    2321        1416 :             MOZ_ASSERT(child, "Don't append null to mChildren");
    2322        1416 :             MOZ_ASSERT(child->mType == childType);
    2323        1416 :             mChildren.AppendElement(child);
    2324             : 
    2325             :             // Oh dear. Something failed during the deserialization.
    2326             :             // We don't know what.  But likely consequences of failed
    2327             :             // deserializations included calls to |AbortCaching| which
    2328             :             // shuts down the cache and closes our streams.
    2329             :             // If that happens, next time through this loop, we die a messy
    2330             :             // death. So, let's just fail now, and propagate that failure
    2331             :             // upward so that the ChromeProtocolHandler knows it can't use
    2332             :             // a cached chrome channel for this.
    2333        1416 :             if (NS_WARN_IF(NS_FAILED(rv)))
    2334           0 :                 return rv;
    2335             :         }
    2336             :     }
    2337             : 
    2338        1297 :     return rv;
    2339             : }
    2340             : 
    2341             : nsresult
    2342        5066 : nsXULPrototypeElement::SetAttrAt(uint32_t aPos, const nsAString& aValue,
    2343             :                                  nsIURI* aDocumentURI)
    2344             : {
    2345        5066 :     NS_PRECONDITION(aPos < mNumAttributes, "out-of-bounds");
    2346             : 
    2347             :     // WARNING!!
    2348             :     // This code is largely duplicated in nsXULElement::SetAttr.
    2349             :     // Any changes should be made to both functions.
    2350             : 
    2351        5066 :     if (!mNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) {
    2352          32 :         mAttributes[aPos].mValue.ParseStringOrAtom(aValue);
    2353             : 
    2354          32 :         return NS_OK;
    2355             :     }
    2356             : 
    2357        6018 :     if (mAttributes[aPos].mName.Equals(nsGkAtoms::id) &&
    2358         984 :         !aValue.IsEmpty()) {
    2359         984 :         mHasIdAttribute = true;
    2360             :         // Store id as atom.
    2361             :         // id="" means that the element has no id. Not that it has
    2362             :         // emptystring as id.
    2363         984 :         mAttributes[aPos].mValue.ParseAtom(aValue);
    2364             : 
    2365         984 :         return NS_OK;
    2366        4050 :     } else if (mAttributes[aPos].mName.Equals(nsGkAtoms::_class)) {
    2367         605 :         mHasClassAttribute = true;
    2368             :         // Compute the element's class list
    2369         605 :         mAttributes[aPos].mValue.ParseAtomArray(aValue);
    2370             : 
    2371         605 :         return NS_OK;
    2372        3445 :     } else if (mAttributes[aPos].mName.Equals(nsGkAtoms::style)) {
    2373           7 :         mHasStyleAttribute = true;
    2374             :         // Parse the element's 'style' attribute
    2375             : 
    2376           7 :         nsCSSParser parser;
    2377             : 
    2378             :         // XXX Get correct Base URI (need GetBaseURI on *prototype* element)
    2379             :         // TODO: If we implement Content Security Policy for chrome documents
    2380             :         // as has been discussed, the CSP should be checked here to see if
    2381             :         // inline styles are allowed to be applied.
    2382             :         RefPtr<css::Declaration> declaration =
    2383          14 :           parser.ParseStyleAttribute(aValue, aDocumentURI, aDocumentURI,
    2384             :                                      // This is basically duplicating what
    2385             :                                      // nsINode::NodePrincipal() does
    2386             :                                      mNodeInfo->NodeInfoManager()->
    2387           7 :                                        DocumentPrincipal());
    2388           7 :         if (declaration) {
    2389           7 :             mAttributes[aPos].mValue.SetTo(declaration.forget(), &aValue);
    2390             : 
    2391           7 :             return NS_OK;
    2392             :         }
    2393             :         // Don't abort if parsing failed, it could just be malformed css.
    2394             :     }
    2395             : 
    2396        3438 :     mAttributes[aPos].mValue.ParseStringOrAtom(aValue);
    2397             : 
    2398        3438 :     return NS_OK;
    2399             : }
    2400             : 
    2401             : void
    2402         393 : nsXULPrototypeElement::Unlink()
    2403             : {
    2404         393 :     mNumAttributes = 0;
    2405         393 :     delete[] mAttributes;
    2406         393 :     mAttributes = nullptr;
    2407         393 :     mChildren.Clear();
    2408         393 : }
    2409             : 
    2410             : void
    2411        1297 : nsXULPrototypeElement::TraceAllScripts(JSTracer* aTrc)
    2412             : {
    2413        2713 :     for (uint32_t i = 0; i < mChildren.Length(); ++i) {
    2414        1416 :         nsXULPrototypeNode* child = mChildren[i];
    2415        1416 :         if (child->mType == nsXULPrototypeNode::eType_Element) {
    2416        1291 :             static_cast<nsXULPrototypeElement*>(child)->TraceAllScripts(aTrc);
    2417         125 :         } else if (child->mType == nsXULPrototypeNode::eType_Script) {
    2418          39 :             static_cast<nsXULPrototypeScript*>(child)->TraceScriptObject(aTrc);
    2419             :         }
    2420             :     }
    2421        1297 : }
    2422             : 
    2423             : //----------------------------------------------------------------------
    2424             : //
    2425             : // nsXULPrototypeScript
    2426             : //
    2427             : 
    2428          39 : nsXULPrototypeScript::nsXULPrototypeScript(uint32_t aLineNo, uint32_t aVersion)
    2429             :     : nsXULPrototypeNode(eType_Script),
    2430             :       mLineNo(aLineNo),
    2431             :       mSrcLoading(false),
    2432             :       mOutOfLine(true),
    2433             :       mSrcLoadWaiters(nullptr),
    2434             :       mLangVersion(aVersion),
    2435          39 :       mScriptObject(nullptr)
    2436             : {
    2437          39 : }
    2438             : 
    2439             : 
    2440           0 : nsXULPrototypeScript::~nsXULPrototypeScript()
    2441             : {
    2442           0 :     UnlinkJSObjects();
    2443           0 : }
    2444             : 
    2445             : nsresult
    2446           0 : nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
    2447             :                                 nsXULPrototypeDocument* aProtoDoc,
    2448             :                                 const nsTArray<RefPtr<mozilla::dom::NodeInfo>> *aNodeInfos)
    2449             : {
    2450           0 :     NS_ENSURE_TRUE(aProtoDoc, NS_ERROR_UNEXPECTED);
    2451             : 
    2452           0 :     AutoJSAPI jsapi;
    2453           0 :     if (!jsapi.Init(xpc::CompilationScope())) {
    2454           0 :         return NS_ERROR_UNEXPECTED;
    2455             :     }
    2456             : 
    2457           0 :     NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nullptr ||
    2458             :                  !mScriptObject,
    2459             :                  "script source still loading when serializing?!");
    2460           0 :     if (!mScriptObject)
    2461           0 :         return NS_ERROR_FAILURE;
    2462             : 
    2463             :     // Write basic prototype data
    2464             :     nsresult rv;
    2465           0 :     rv = aStream->Write32(mLineNo);
    2466           0 :     if (NS_FAILED(rv)) return rv;
    2467           0 :     rv = aStream->Write32(mLangVersion);
    2468           0 :     if (NS_FAILED(rv)) return rv;
    2469             : 
    2470           0 :     JSContext* cx = jsapi.cx();
    2471           0 :     JS::Rooted<JSScript*> script(cx, mScriptObject);
    2472           0 :     MOZ_ASSERT(xpc::CompilationScope() == JS::CurrentGlobalOrNull(cx));
    2473           0 :     return nsContentUtils::XPConnect()->WriteScript(aStream, cx, script);
    2474             : }
    2475             : 
    2476             : nsresult
    2477           0 : nsXULPrototypeScript::SerializeOutOfLine(nsIObjectOutputStream* aStream,
    2478             :                                          nsXULPrototypeDocument* aProtoDoc)
    2479             : {
    2480           0 :     nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
    2481             : 
    2482           0 :     bool isChrome = false;
    2483           0 :     if (NS_FAILED(mSrcURI->SchemeIs("chrome", &isChrome)) || !isChrome)
    2484             :        // Don't cache scripts that don't come from chrome uris.
    2485           0 :        return rv;
    2486             : 
    2487           0 :     nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
    2488           0 :     if (!cache)
    2489           0 :         return NS_ERROR_OUT_OF_MEMORY;
    2490             : 
    2491           0 :     NS_ASSERTION(cache->IsEnabled(),
    2492             :                  "writing to the cache file, but the XUL cache is off?");
    2493             :     bool exists;
    2494           0 :     cache->HasData(mSrcURI, &exists);
    2495             : 
    2496             :     /* return will be NS_OK from GetAsciiSpec.
    2497             :      * that makes no sense.
    2498             :      * nor does returning NS_OK from HasMuxedDocument.
    2499             :      * XXX return something meaningful.
    2500             :      */
    2501           0 :     if (exists)
    2502           0 :         return NS_OK;
    2503             : 
    2504           0 :     nsCOMPtr<nsIObjectOutputStream> oos;
    2505           0 :     rv = cache->GetOutputStream(mSrcURI, getter_AddRefs(oos));
    2506           0 :     NS_ENSURE_SUCCESS(rv, rv);
    2507             : 
    2508           0 :     nsresult tmp = Serialize(oos, aProtoDoc, nullptr);
    2509           0 :     if (NS_FAILED(tmp)) {
    2510           0 :       rv = tmp;
    2511             :     }
    2512           0 :     tmp = cache->FinishOutputStream(mSrcURI);
    2513           0 :     if (NS_FAILED(tmp)) {
    2514           0 :       rv = tmp;
    2515             :     }
    2516             : 
    2517           0 :     if (NS_FAILED(rv))
    2518           0 :         cache->AbortCaching();
    2519           0 :     return rv;
    2520             : }
    2521             : 
    2522             : 
    2523             : nsresult
    2524          38 : nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream,
    2525             :                                   nsXULPrototypeDocument* aProtoDoc,
    2526             :                                   nsIURI* aDocumentURI,
    2527             :                                   const nsTArray<RefPtr<mozilla::dom::NodeInfo>> *aNodeInfos)
    2528             : {
    2529             :     nsresult rv;
    2530          38 :     NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nullptr ||
    2531             :                  !mScriptObject,
    2532             :                  "prototype script not well-initialized when deserializing?!");
    2533             : 
    2534             :     // Read basic prototype data
    2535          38 :     rv = aStream->Read32(&mLineNo);
    2536          38 :     if (NS_FAILED(rv)) return rv;
    2537          38 :     rv = aStream->Read32(&mLangVersion);
    2538          38 :     if (NS_FAILED(rv)) return rv;
    2539             : 
    2540          76 :     AutoJSAPI jsapi;
    2541          38 :     if (!jsapi.Init(xpc::CompilationScope())) {
    2542           0 :         return NS_ERROR_UNEXPECTED;
    2543             :     }
    2544          38 :     JSContext* cx = jsapi.cx();
    2545             : 
    2546          76 :     JS::Rooted<JSScript*> newScriptObject(cx);
    2547          76 :     rv = nsContentUtils::XPConnect()->ReadScript(aStream, cx,
    2548          76 :                                                  newScriptObject.address());
    2549          38 :     NS_ENSURE_SUCCESS(rv, rv);
    2550          38 :     Set(newScriptObject);
    2551          38 :     return NS_OK;
    2552             : }
    2553             : 
    2554             : 
    2555             : nsresult
    2556          38 : nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput,
    2557             :                                            nsXULPrototypeDocument* aProtoDoc)
    2558             : {
    2559             :     // Keep track of failure via rv, so we can
    2560             :     // AbortCaching if things look bad.
    2561          38 :     nsresult rv = NS_OK;
    2562          38 :     nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
    2563             : 
    2564          76 :     nsCOMPtr<nsIObjectInputStream> objectInput = aInput;
    2565          38 :     if (cache) {
    2566          38 :         bool useXULCache = true;
    2567          38 :         if (mSrcURI) {
    2568             :             // NB: we must check the XUL script cache early, to avoid
    2569             :             // multiple deserialization attempts for a given script.
    2570             :             // Note that XULDocument::LoadScript
    2571             :             // checks the XUL script cache too, in order to handle the
    2572             :             // serialization case.
    2573             :             //
    2574             :             // We need do this only for <script src='strres.js'> and the
    2575             :             // like, i.e., out-of-line scripts that are included by several
    2576             :             // different XUL documents stored in the cache file.
    2577          38 :             useXULCache = cache->IsEnabled();
    2578             : 
    2579          38 :             if (useXULCache) {
    2580             :                 JSScript* newScriptObject =
    2581          38 :                     cache->GetScript(mSrcURI);
    2582          38 :                 if (newScriptObject)
    2583           1 :                     Set(newScriptObject);
    2584             :             }
    2585             :         }
    2586             : 
    2587          38 :         if (!mScriptObject) {
    2588          37 :             if (mSrcURI) {
    2589          37 :                 rv = cache->GetInputStream(mSrcURI, getter_AddRefs(objectInput));
    2590             :             }
    2591             :             // If !mSrcURI, we have an inline script. We shouldn't have
    2592             :             // to do anything else in that case, I think.
    2593             : 
    2594             :             // We do reflect errors into rv, but our caller may want to
    2595             :             // ignore our return value, because mScriptObject will be null
    2596             :             // after any error, and that suffices to cause the script to
    2597             :             // be reloaded (from the src= URI, if any) and recompiled.
    2598             :             // We're better off slow-loading than bailing out due to a
    2599             :             // error.
    2600          37 :             if (NS_SUCCEEDED(rv))
    2601          37 :                 rv = Deserialize(objectInput, aProtoDoc, nullptr, nullptr);
    2602             : 
    2603          37 :             if (NS_SUCCEEDED(rv)) {
    2604          37 :                 if (useXULCache && mSrcURI) {
    2605          37 :                     bool isChrome = false;
    2606          37 :                     mSrcURI->SchemeIs("chrome", &isChrome);
    2607          37 :                     if (isChrome) {
    2608          74 :                         JS::Rooted<JSScript*> script(RootingCx(), GetScriptObject());
    2609          37 :                         cache->PutScript(mSrcURI, script);
    2610             :                     }
    2611             :                 }
    2612          37 :                 cache->FinishInputStream(mSrcURI);
    2613             :             } else {
    2614             :                 // If mSrcURI is not in the cache,
    2615             :                 // rv will be NS_ERROR_NOT_AVAILABLE and we'll try to
    2616             :                 // update the cache file to hold a serialization of
    2617             :                 // this script, once it has finished loading.
    2618           0 :                 if (rv != NS_ERROR_NOT_AVAILABLE)
    2619           0 :                     cache->AbortCaching();
    2620             :             }
    2621             :         }
    2622             :     }
    2623          76 :     return rv;
    2624             : }
    2625             : 
    2626           0 : class NotifyOffThreadScriptCompletedRunnable : public Runnable
    2627             : {
    2628             :     // An array of all outstanding script receivers. All reference counting of
    2629             :     // these objects happens on the main thread. When we return to the main
    2630             :     // thread from script compilation we make sure our receiver is still in
    2631             :     // this array (still alive) before proceeding. This array is cleared during
    2632             :     // shutdown, potentially before all outstanding script compilations have
    2633             :     // finished. We do not need to worry about pointer replay here, because
    2634             :     // a) we should not be starting script compilation after clearing this
    2635             :     // array and b) in all other cases the receiver will still be alive.
    2636             :     static StaticAutoPtr<nsTArray<nsCOMPtr<nsIOffThreadScriptReceiver>>> sReceivers;
    2637             :     static bool sSetupClearOnShutdown;
    2638             : 
    2639             :     nsIOffThreadScriptReceiver* mReceiver;
    2640             :     void *mToken;
    2641             : 
    2642             : public:
    2643           0 :   NotifyOffThreadScriptCompletedRunnable(nsIOffThreadScriptReceiver* aReceiver,
    2644             :                                          void* aToken)
    2645           0 :     : mozilla::Runnable("NotifyOffThreadScriptCompletedRunnable")
    2646             :     , mReceiver(aReceiver)
    2647           0 :     , mToken(aToken)
    2648             :   {
    2649           0 :   }
    2650             : 
    2651           0 :   static void NoteReceiver(nsIOffThreadScriptReceiver* aReceiver)
    2652             :   {
    2653           0 :     if (!sSetupClearOnShutdown) {
    2654           0 :       ClearOnShutdown(&sReceivers);
    2655           0 :       sSetupClearOnShutdown = true;
    2656           0 :       sReceivers = new nsTArray<nsCOMPtr<nsIOffThreadScriptReceiver>>();
    2657             :     }
    2658             : 
    2659             :     // If we ever crash here, it's because we tried to lazy compile script
    2660             :     // too late in shutdown.
    2661           0 :     sReceivers->AppendElement(aReceiver);
    2662           0 :     }
    2663             : 
    2664             :     NS_DECL_NSIRUNNABLE
    2665             : };
    2666             : 
    2667           3 : StaticAutoPtr<nsTArray<nsCOMPtr<nsIOffThreadScriptReceiver>>> NotifyOffThreadScriptCompletedRunnable::sReceivers;
    2668             : bool NotifyOffThreadScriptCompletedRunnable::sSetupClearOnShutdown = false;
    2669             : 
    2670             : NS_IMETHODIMP
    2671           0 : NotifyOffThreadScriptCompletedRunnable::Run()
    2672             : {
    2673           0 :     MOZ_ASSERT(NS_IsMainThread());
    2674             : 
    2675           0 :     JS::Rooted<JSScript*> script(RootingCx());
    2676             :     {
    2677           0 :         AutoJSAPI jsapi;
    2678           0 :         if (!jsapi.Init(xpc::CompilationScope())) {
    2679             :             // Now what?  I guess we just leak... this should probably never
    2680             :             // happen.
    2681           0 :             return NS_ERROR_UNEXPECTED;
    2682             :         }
    2683           0 :         JSContext* cx = jsapi.cx();
    2684           0 :         script = JS::FinishOffThreadScript(cx, mToken);
    2685             :     }
    2686             : 
    2687           0 :     if (!sReceivers) {
    2688             :         // We've already shut down.
    2689           0 :         return NS_OK;
    2690             :     }
    2691             : 
    2692           0 :     auto index = sReceivers->IndexOf(mReceiver);
    2693           0 :     MOZ_RELEASE_ASSERT(index != sReceivers->NoIndex);
    2694           0 :     nsCOMPtr<nsIOffThreadScriptReceiver> receiver = (*sReceivers)[index].forget();
    2695           0 :     sReceivers->RemoveElementAt(index);
    2696             : 
    2697           0 :     return receiver->OnScriptCompileComplete(script, script ? NS_OK : NS_ERROR_FAILURE);
    2698             : }
    2699             : 
    2700             : static void
    2701           0 : OffThreadScriptReceiverCallback(void *aToken, void *aCallbackData)
    2702             : {
    2703             :     // Be careful not to adjust the refcount on the receiver, as this callback
    2704             :     // may be invoked off the main thread.
    2705           0 :     nsIOffThreadScriptReceiver* aReceiver = static_cast<nsIOffThreadScriptReceiver*>(aCallbackData);
    2706             :     RefPtr<NotifyOffThreadScriptCompletedRunnable> notify =
    2707           0 :         new NotifyOffThreadScriptCompletedRunnable(aReceiver, aToken);
    2708           0 :     NS_DispatchToMainThread(notify);
    2709           0 : }
    2710             : 
    2711             : nsresult
    2712           0 : nsXULPrototypeScript::Compile(JS::SourceBufferHolder& aSrcBuf,
    2713             :                               nsIURI* aURI, uint32_t aLineNo,
    2714             :                               nsIDocument* aDocument,
    2715             :                               nsIOffThreadScriptReceiver *aOffThreadReceiver /* = nullptr */)
    2716             : {
    2717             :     // We'll compile the script in the compilation scope.
    2718           0 :     AutoJSAPI jsapi;
    2719           0 :     if (!jsapi.Init(xpc::CompilationScope())) {
    2720           0 :         return NS_ERROR_UNEXPECTED;
    2721             :     }
    2722           0 :     JSContext* cx = jsapi.cx();
    2723             : 
    2724             :     nsresult rv;
    2725           0 :     nsAutoCString urlspec;
    2726           0 :     nsContentUtils::GetWrapperSafeScriptFilename(aDocument, aURI, urlspec, &rv);
    2727           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
    2728           0 :       return rv;
    2729             :     }
    2730             : 
    2731             :     // Ok, compile it to create a prototype script object!
    2732           0 :     NS_ENSURE_TRUE(JSVersion(mLangVersion) != JSVERSION_UNKNOWN, NS_OK);
    2733           0 :     JS::CompileOptions options(cx);
    2734           0 :     options.setIntroductionType("scriptElement")
    2735           0 :            .setFileAndLine(urlspec.get(), aLineNo)
    2736           0 :            .setVersion(JSVersion(mLangVersion));
    2737             :     // If the script was inline, tell the JS parser to save source for
    2738             :     // Function.prototype.toSource(). If it's out of line, we retrieve the
    2739             :     // source from the files on demand.
    2740           0 :     options.setSourceIsLazy(mOutOfLine);
    2741           0 :     JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
    2742           0 :     if (scope) {
    2743           0 :       JS::ExposeObjectToActiveJS(scope);
    2744             :     }
    2745             : 
    2746           0 :     if (aOffThreadReceiver && JS::CanCompileOffThread(cx, options, aSrcBuf.length())) {
    2747           0 :         if (!JS::CompileOffThread(cx, options,
    2748             :                                   aSrcBuf.get(), aSrcBuf.length(),
    2749             :                                   OffThreadScriptReceiverCallback,
    2750             :                                   static_cast<void*>(aOffThreadReceiver))) {
    2751           0 :             return NS_ERROR_OUT_OF_MEMORY;
    2752             :         }
    2753           0 :         NotifyOffThreadScriptCompletedRunnable::NoteReceiver(aOffThreadReceiver);
    2754             :     } else {
    2755           0 :         JS::Rooted<JSScript*> script(cx);
    2756           0 :         if (!JS::Compile(cx, options, aSrcBuf, &script))
    2757           0 :             return NS_ERROR_OUT_OF_MEMORY;
    2758           0 :         Set(script);
    2759             :     }
    2760           0 :     return NS_OK;
    2761             : }
    2762             : 
    2763             : nsresult
    2764           0 : nsXULPrototypeScript::Compile(const char16_t* aText,
    2765             :                               int32_t aTextLength,
    2766             :                               nsIURI* aURI,
    2767             :                               uint32_t aLineNo,
    2768             :                               nsIDocument* aDocument,
    2769             :                               nsIOffThreadScriptReceiver *aOffThreadReceiver /* = nullptr */)
    2770             : {
    2771             :   JS::SourceBufferHolder srcBuf(aText, aTextLength,
    2772           0 :                                 JS::SourceBufferHolder::NoOwnership);
    2773           0 :   return Compile(srcBuf, aURI, aLineNo, aDocument, aOffThreadReceiver);
    2774             : }
    2775             : 
    2776             : void
    2777           0 : nsXULPrototypeScript::UnlinkJSObjects()
    2778             : {
    2779           0 :     if (mScriptObject) {
    2780           0 :         mScriptObject = nullptr;
    2781           0 :         mozilla::DropJSObjects(this);
    2782             :     }
    2783           0 : }
    2784             : 
    2785             : void
    2786          39 : nsXULPrototypeScript::Set(JSScript* aObject)
    2787             : {
    2788          39 :     MOZ_ASSERT(!mScriptObject, "Leaking script object.");
    2789          39 :     if (!aObject) {
    2790           0 :         mScriptObject = nullptr;
    2791           0 :         return;
    2792             :     }
    2793             : 
    2794          39 :     mScriptObject = aObject;
    2795          39 :     mozilla::HoldJSObjects(this);
    2796             : }
    2797             : 
    2798             : //----------------------------------------------------------------------
    2799             : //
    2800             : // nsXULPrototypeText
    2801             : //
    2802             : 
    2803             : nsresult
    2804           0 : nsXULPrototypeText::Serialize(nsIObjectOutputStream* aStream,
    2805             :                               nsXULPrototypeDocument* aProtoDoc,
    2806             :                               const nsTArray<RefPtr<mozilla::dom::NodeInfo>> *aNodeInfos)
    2807             : {
    2808             :     nsresult rv;
    2809             : 
    2810             :     // Write basic prototype data
    2811           0 :     rv = aStream->Write32(mType);
    2812             : 
    2813           0 :     nsresult tmp = aStream->WriteWStringZ(mValue.get());
    2814           0 :     if (NS_FAILED(tmp)) {
    2815           0 :       rv = tmp;
    2816             :     }
    2817             : 
    2818           0 :     return rv;
    2819             : }
    2820             : 
    2821             : nsresult
    2822          86 : nsXULPrototypeText::Deserialize(nsIObjectInputStream* aStream,
    2823             :                                 nsXULPrototypeDocument* aProtoDoc,
    2824             :                                 nsIURI* aDocumentURI,
    2825             :                                 const nsTArray<RefPtr<mozilla::dom::NodeInfo>> *aNodeInfos)
    2826             : {
    2827          86 :     nsresult rv = aStream->ReadString(mValue);
    2828          86 :     if (NS_WARN_IF(NS_FAILED(rv))) {
    2829           0 :         return rv;
    2830             :     }
    2831          86 :     return NS_OK;
    2832             : }
    2833             : 
    2834             : //----------------------------------------------------------------------
    2835             : //
    2836             : // nsXULPrototypePI
    2837             : //
    2838             : 
    2839             : nsresult
    2840           0 : nsXULPrototypePI::Serialize(nsIObjectOutputStream* aStream,
    2841             :                             nsXULPrototypeDocument* aProtoDoc,
    2842             :                             const nsTArray<RefPtr<mozilla::dom::NodeInfo>> *aNodeInfos)
    2843             : {
    2844             :     nsresult rv;
    2845             : 
    2846             :     // Write basic prototype data
    2847           0 :     rv = aStream->Write32(mType);
    2848             : 
    2849           0 :     nsresult tmp = aStream->WriteWStringZ(mTarget.get());
    2850           0 :     if (NS_FAILED(tmp)) {
    2851           0 :       rv = tmp;
    2852             :     }
    2853           0 :     tmp = aStream->WriteWStringZ(mData.get());
    2854           0 :     if (NS_FAILED(tmp)) {
    2855           0 :       rv = tmp;
    2856             :     }
    2857             : 
    2858           0 :     return rv;
    2859             : }
    2860             : 
    2861             : nsresult
    2862           9 : nsXULPrototypePI::Deserialize(nsIObjectInputStream* aStream,
    2863             :                               nsXULPrototypeDocument* aProtoDoc,
    2864             :                               nsIURI* aDocumentURI,
    2865             :                               const nsTArray<RefPtr<mozilla::dom::NodeInfo>> *aNodeInfos)
    2866             : {
    2867             :     nsresult rv;
    2868             : 
    2869           9 :     rv = aStream->ReadString(mTarget);
    2870           9 :     if (NS_FAILED(rv)) return rv;
    2871           9 :     rv = aStream->ReadString(mData);
    2872           9 :     if (NS_FAILED(rv)) return rv;
    2873             : 
    2874           9 :     return rv;
    2875             : }

Generated by: LCOV version 1.13