1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 /*
7 
8   The base XUL element class and associates.
9 
10 */
11 
12 #ifndef nsXULElement_h__
13 #define nsXULElement_h__
14 
15 #include <stdint.h>
16 #include <stdio.h>
17 #include "ErrorList.h"
18 #include "js/RootingAPI.h"
19 #include "js/SourceText.h"
20 #include "js/TracingAPI.h"
21 #include "mozilla/AlreadyAddRefed.h"
22 #include "mozilla/Assertions.h"
23 #include "mozilla/Attributes.h"
24 #include "mozilla/BasicEvents.h"
25 #include "mozilla/RefPtr.h"
26 #include "mozilla/dom/DOMString.h"
27 #include "mozilla/dom/Element.h"
28 #include "mozilla/dom/FragmentOrElement.h"
29 #include "mozilla/dom/FromParser.h"
30 #include "mozilla/dom/NameSpaceConstants.h"
31 #include "mozilla/dom/NodeInfo.h"
32 #include "nsAtom.h"
33 #include "nsAttrName.h"
34 #include "nsAttrValue.h"
35 #include "nsCOMPtr.h"
36 #include "nsCaseTreatment.h"
37 #include "nsChangeHint.h"
38 #include "nsCycleCollectionParticipant.h"
39 #include "nsGkAtoms.h"
40 #include "nsIContent.h"
41 #include "nsINode.h"
42 #include "nsISupports.h"
43 #include "nsLiteralString.h"
44 #include "nsString.h"
45 #include "nsStyledElement.h"
46 #include "nsTArray.h"
47 #include "nsTLiteralString.h"
48 #include "nscore.h"
49 
50 class JSObject;
51 class JSScript;
52 class nsAttrValueOrString;
53 class nsIControllers;
54 class nsIObjectInputStream;
55 class nsIObjectOutputStream;
56 class nsIOffThreadScriptReceiver;
57 class nsIPrincipal;
58 class nsIURI;
59 class nsXULPrototypeDocument;
60 class nsXULPrototypeNode;
61 struct JSContext;
62 
63 typedef nsTArray<RefPtr<nsXULPrototypeNode>> nsPrototypeArray;
64 
65 namespace JS {
66 class CompileOptions;
67 }
68 
69 namespace mozilla {
70 class ErrorResult;
71 class EventChainPreVisitor;
72 class EventListenerManager;
73 namespace css {
74 class StyleRule;
75 }  // namespace css
76 namespace dom {
77 class Document;
78 class HTMLIFrameElement;
79 class PrototypeDocumentContentSink;
80 enum class CallerType : uint32_t;
81 }  // namespace dom
82 }  // namespace mozilla
83 
84 ////////////////////////////////////////////////////////////////////////
85 
86 #ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
87 #  define XUL_PROTOTYPE_ATTRIBUTE_METER(counter) \
88     (nsXULPrototypeAttribute::counter++)
89 #else
90 #  define XUL_PROTOTYPE_ATTRIBUTE_METER(counter) ((void)0)
91 #endif
92 
93 /**
94 
95   A prototype attribute for an nsXULPrototypeElement.
96 
97  */
98 
99 class nsXULPrototypeAttribute {
100  public:
nsXULPrototypeAttribute()101   nsXULPrototypeAttribute()
102       : mName(nsGkAtoms::id)  // XXX this is a hack, but names have to have a
103                               // value
104   {
105     XUL_PROTOTYPE_ATTRIBUTE_METER(gNumAttributes);
106     MOZ_COUNT_CTOR(nsXULPrototypeAttribute);
107   }
108 
109   ~nsXULPrototypeAttribute();
110 
111   nsAttrName mName;
112   nsAttrValue mValue;
113 
114 #ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
115   static uint32_t gNumElements;
116   static uint32_t gNumAttributes;
117   static uint32_t gNumCacheTests;
118   static uint32_t gNumCacheHits;
119   static uint32_t gNumCacheSets;
120   static uint32_t gNumCacheFills;
121 #endif /* !XUL_PROTOTYPE_ATTRIBUTE_METERING */
122 };
123 
124 /**
125 
126   A prototype content model element that holds the "primordial" values
127   that have been parsed from the original XUL document.
128 
129  */
130 
131 class nsXULPrototypeNode {
132  public:
133   enum Type { eType_Element, eType_Script, eType_Text, eType_PI };
134 
135   Type mType;
136 
137   virtual nsresult Serialize(
138       nsIObjectOutputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
139       const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) = 0;
140   virtual nsresult Deserialize(
141       nsIObjectInputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
142       nsIURI* aDocumentURI,
143       const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) = 0;
144 
145   /**
146    * The prototype document must call ReleaseSubtree when it is going
147    * away.  This makes the parents through the tree stop owning their
148    * children, whether or not the parent's reference count is zero.
149    * Individual elements may still own individual prototypes, but
150    * those prototypes no longer remember their children to allow them
151    * to be constructed.
152    */
ReleaseSubtree()153   virtual void ReleaseSubtree() {}
154 
155   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(nsXULPrototypeNode)
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsXULPrototypeNode)156   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsXULPrototypeNode)
157 
158  protected:
159   explicit nsXULPrototypeNode(Type aType) : mType(aType) {}
160   virtual ~nsXULPrototypeNode() = default;
161 };
162 
163 class nsXULPrototypeElement : public nsXULPrototypeNode {
164  public:
165   explicit nsXULPrototypeElement(mozilla::dom::NodeInfo* aNodeInfo = nullptr)
nsXULPrototypeNode(eType_Element)166       : nsXULPrototypeNode(eType_Element),
167         mNodeInfo(aNodeInfo),
168         mHasIdAttribute(false),
169         mHasClassAttribute(false),
170         mHasStyleAttribute(false),
171         mIsAtom(nullptr) {}
172 
173  private:
~nsXULPrototypeElement()174   virtual ~nsXULPrototypeElement() { Unlink(); }
175 
176  public:
ReleaseSubtree()177   virtual void ReleaseSubtree() override {
178     for (int32_t i = mChildren.Length() - 1; i >= 0; i--) {
179       if (mChildren[i].get()) mChildren[i]->ReleaseSubtree();
180     }
181     mChildren.Clear();
182     nsXULPrototypeNode::ReleaseSubtree();
183   }
184 
185   virtual nsresult Serialize(
186       nsIObjectOutputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
187       const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) override;
188   virtual nsresult Deserialize(
189       nsIObjectInputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
190       nsIURI* aDocumentURI,
191       const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) override;
192 
193   nsresult SetAttrAt(uint32_t aPos, const nsAString& aValue,
194                      nsIURI* aDocumentURI);
195 
196   void Unlink();
197 
198   // Trace all scripts held by this element and its children.
199   void TraceAllScripts(JSTracer* aTrc);
200 
201   nsPrototypeArray mChildren;
202 
203   RefPtr<mozilla::dom::NodeInfo> mNodeInfo;
204 
205   uint32_t mHasIdAttribute : 1;
206   uint32_t mHasClassAttribute : 1;
207   uint32_t mHasStyleAttribute : 1;
208   nsTArray<nsXULPrototypeAttribute> mAttributes;  // [OWNER]
209   RefPtr<nsAtom> mIsAtom;
210 };
211 
212 class nsXULPrototypeScript : public nsXULPrototypeNode {
213  public:
214   explicit nsXULPrototypeScript(uint32_t aLineNo);
215 
216  private:
217   virtual ~nsXULPrototypeScript();
218 
219   void FillCompileOptions(JS::CompileOptions& options);
220 
221  public:
222   virtual nsresult Serialize(
223       nsIObjectOutputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
224       const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) override;
225   nsresult SerializeOutOfLine(nsIObjectOutputStream* aStream,
226                               nsXULPrototypeDocument* aProtoDoc);
227   virtual nsresult Deserialize(
228       nsIObjectInputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
229       nsIURI* aDocumentURI,
230       const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) override;
231   nsresult DeserializeOutOfLine(nsIObjectInputStream* aInput,
232                                 nsXULPrototypeDocument* aProtoDoc);
233 
234   nsresult Compile(const char16_t* aText, size_t aTextLength,
235                    JS::SourceOwnership aOwnership, nsIURI* aURI,
236                    uint32_t aLineNo, mozilla::dom::Document* aDocument,
237                    nsIOffThreadScriptReceiver* aOffThreadReceiver = nullptr);
238 
239   void UnlinkJSObjects();
240 
241   void Set(JSScript* aObject);
242 
HasScriptObject()243   bool HasScriptObject() {
244     // Conversion to bool doesn't trigger mScriptObject's read barrier.
245     return mScriptObject;
246   }
247 
GetScriptObject()248   JSScript* GetScriptObject() { return mScriptObject; }
249 
TraceScriptObject(JSTracer * aTrc)250   void TraceScriptObject(JSTracer* aTrc) {
251     JS::TraceEdge(aTrc, &mScriptObject, "active window XUL prototype script");
252   }
253 
Trace(const TraceCallbacks & aCallbacks,void * aClosure)254   void Trace(const TraceCallbacks& aCallbacks, void* aClosure) {
255     if (mScriptObject) {
256       aCallbacks.Trace(&mScriptObject, "mScriptObject", aClosure);
257     }
258   }
259 
260   nsCOMPtr<nsIURI> mSrcURI;
261   uint32_t mLineNo;
262   bool mSrcLoading;
263   bool mOutOfLine;
264   mozilla::dom::PrototypeDocumentContentSink*
265       mSrcLoadWaiters;  // [OWNER] but not COMPtr
266  private:
267   JS::Heap<JSScript*> mScriptObject;
268 };
269 
270 class nsXULPrototypeText : public nsXULPrototypeNode {
271  public:
nsXULPrototypeText()272   nsXULPrototypeText() : nsXULPrototypeNode(eType_Text) {}
273 
274  private:
275   virtual ~nsXULPrototypeText() = default;
276 
277  public:
278   virtual nsresult Serialize(
279       nsIObjectOutputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
280       const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) override;
281   virtual nsresult Deserialize(
282       nsIObjectInputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
283       nsIURI* aDocumentURI,
284       const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) override;
285 
286   nsString mValue;
287 };
288 
289 class nsXULPrototypePI : public nsXULPrototypeNode {
290  public:
nsXULPrototypePI()291   nsXULPrototypePI() : nsXULPrototypeNode(eType_PI) {}
292 
293  private:
294   virtual ~nsXULPrototypePI() = default;
295 
296  public:
297   virtual nsresult Serialize(
298       nsIObjectOutputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
299       const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) override;
300   virtual nsresult Deserialize(
301       nsIObjectInputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
302       nsIURI* aDocumentURI,
303       const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) override;
304 
305   nsString mTarget;
306   nsString mData;
307 };
308 
309 ////////////////////////////////////////////////////////////////////////
310 
311 /**
312 
313   The XUL element.
314 
315  */
316 
317 #define XUL_ELEMENT_FLAG_BIT(n_) \
318   NODE_FLAG_BIT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_))
319 
320 // XUL element specific bits
321 enum {
322   XUL_ELEMENT_HAS_CONTENTMENU_LISTENER = XUL_ELEMENT_FLAG_BIT(0),
323   XUL_ELEMENT_HAS_POPUP_LISTENER = XUL_ELEMENT_FLAG_BIT(1)
324 };
325 
326 ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
327 
328 #undef XUL_ELEMENT_FLAG_BIT
329 
330 class nsXULElement : public nsStyledElement {
331  protected:
332   typedef mozilla::dom::Document Document;
333 
334   // Use Construct to construct elements instead of this constructor.
335   explicit nsXULElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
336 
337  public:
338   using Element::Blur;
339   using Element::Focus;
340 
341   static nsresult CreateFromPrototype(nsXULPrototypeElement* aPrototype,
342                                       Document* aDocument, bool aIsScriptable,
343                                       bool aIsRoot,
344                                       mozilla::dom::Element** aResult);
345 
346   // This is the constructor for nsXULElements.
347   static nsXULElement* Construct(
348       already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
349 
350   NS_IMPL_FROMNODE(nsXULElement, kNameSpaceID_XUL)
351 
352   // nsISupports
353   NS_DECL_ISUPPORTS_INHERITED
354   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULElement, nsStyledElement)
355 
356   // nsINode
357   void GetEventTargetParent(mozilla::EventChainPreVisitor& aVisitor) override;
358   MOZ_CAN_RUN_SCRIPT_BOUNDARY
359   virtual nsresult PreHandleEvent(
360       mozilla::EventChainVisitor& aVisitor) override;
361   // nsIContent
362   virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
363   virtual void UnbindFromTree(bool aNullParent) override;
364   virtual void DestroyContent() override;
365   virtual void DoneAddingChildren(bool aHaveNotified) override;
366 
367 #ifdef MOZ_DOM_LIST
368   virtual void List(FILE* out, int32_t aIndent) const override;
DumpContent(FILE * out,int32_t aIndent,bool aDumpAll)369   virtual void DumpContent(FILE* out, int32_t aIndent,
370                            bool aDumpAll) const override {}
371 #endif
372 
373   MOZ_CAN_RUN_SCRIPT int32_t ScreenX();
374   MOZ_CAN_RUN_SCRIPT int32_t ScreenY();
375 
376   MOZ_CAN_RUN_SCRIPT bool HasMenu();
377   MOZ_CAN_RUN_SCRIPT void OpenMenu(bool aOpenFlag);
378 
379   MOZ_CAN_RUN_SCRIPT virtual bool PerformAccesskey(
380       bool aKeyCausesActivation, bool aIsTrustedEvent) override;
381   void ClickWithInputSource(uint16_t aInputSource, bool aIsTrustedEvent);
382 
383   virtual bool IsNodeOfType(uint32_t aFlags) const override;
384   virtual bool IsFocusableInternal(int32_t* aTabIndex,
385                                    bool aWithMouse) override;
386 
387   virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
388                                               int32_t aModType) const override;
389   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
390 
391   virtual nsresult Clone(mozilla::dom::NodeInfo*,
392                          nsINode** aResult) const override;
393 
394   virtual void RecompileScriptEventListeners() override;
395 
396   virtual bool IsEventAttributeNameInternal(nsAtom* aName) override;
397 
398   typedef mozilla::dom::DOMString DOMString;
GetXULAttr(nsAtom * aName,DOMString & aResult)399   void GetXULAttr(nsAtom* aName, DOMString& aResult) const {
400     GetAttr(kNameSpaceID_None, aName, aResult);
401   }
SetXULAttr(nsAtom * aName,const nsAString & aValue,mozilla::ErrorResult & aError)402   void SetXULAttr(nsAtom* aName, const nsAString& aValue,
403                   mozilla::ErrorResult& aError) {
404     SetAttr(aName, aValue, aError);
405   }
GetXULBoolAttr(nsAtom * aName)406   bool GetXULBoolAttr(nsAtom* aName) const {
407     return AttrValueIs(kNameSpaceID_None, aName, u"true"_ns, eCaseMatters);
408   }
SetXULBoolAttr(nsAtom * aName,bool aValue)409   void SetXULBoolAttr(nsAtom* aName, bool aValue) {
410     if (aValue) {
411       SetAttr(kNameSpaceID_None, aName, u"true"_ns, true);
412     } else {
413       UnsetAttr(kNameSpaceID_None, aName, true);
414     }
415   }
416 
417   // WebIDL API
GetFlex(DOMString & aValue)418   void GetFlex(DOMString& aValue) const { GetXULAttr(nsGkAtoms::flex, aValue); }
SetFlex(const nsAString & aValue,mozilla::ErrorResult & rv)419   void SetFlex(const nsAString& aValue, mozilla::ErrorResult& rv) {
420     SetXULAttr(nsGkAtoms::flex, aValue, rv);
421   }
Hidden()422   bool Hidden() const { return BoolAttrIsTrue(nsGkAtoms::hidden); }
SetHidden(bool aHidden)423   void SetHidden(bool aHidden) { SetXULBoolAttr(nsGkAtoms::hidden, aHidden); }
Collapsed()424   bool Collapsed() const { return BoolAttrIsTrue(nsGkAtoms::collapsed); }
SetCollapsed(bool aCollapsed)425   void SetCollapsed(bool aCollapsed) {
426     SetXULBoolAttr(nsGkAtoms::collapsed, aCollapsed);
427   }
GetObserves(DOMString & aValue)428   void GetObserves(DOMString& aValue) const {
429     GetXULAttr(nsGkAtoms::observes, aValue);
430   }
SetObserves(const nsAString & aValue,mozilla::ErrorResult & rv)431   void SetObserves(const nsAString& aValue, mozilla::ErrorResult& rv) {
432     SetXULAttr(nsGkAtoms::observes, aValue, rv);
433   }
GetMenu(DOMString & aValue)434   void GetMenu(DOMString& aValue) const { GetXULAttr(nsGkAtoms::menu, aValue); }
SetMenu(const nsAString & aValue,mozilla::ErrorResult & rv)435   void SetMenu(const nsAString& aValue, mozilla::ErrorResult& rv) {
436     SetXULAttr(nsGkAtoms::menu, aValue, rv);
437   }
GetContextMenu(DOMString & aValue)438   void GetContextMenu(DOMString& aValue) {
439     GetXULAttr(nsGkAtoms::contextmenu, aValue);
440   }
SetContextMenu(const nsAString & aValue,mozilla::ErrorResult & rv)441   void SetContextMenu(const nsAString& aValue, mozilla::ErrorResult& rv) {
442     SetXULAttr(nsGkAtoms::contextmenu, aValue, rv);
443   }
GetTooltip(DOMString & aValue)444   void GetTooltip(DOMString& aValue) const {
445     GetXULAttr(nsGkAtoms::tooltip, aValue);
446   }
SetTooltip(const nsAString & aValue,mozilla::ErrorResult & rv)447   void SetTooltip(const nsAString& aValue, mozilla::ErrorResult& rv) {
448     SetXULAttr(nsGkAtoms::tooltip, aValue, rv);
449   }
GetWidth(DOMString & aValue)450   void GetWidth(DOMString& aValue) const {
451     GetXULAttr(nsGkAtoms::width, aValue);
452   }
SetWidth(const nsAString & aValue,mozilla::ErrorResult & rv)453   void SetWidth(const nsAString& aValue, mozilla::ErrorResult& rv) {
454     SetXULAttr(nsGkAtoms::width, aValue, rv);
455   }
GetHeight(DOMString & aValue)456   void GetHeight(DOMString& aValue) { GetXULAttr(nsGkAtoms::height, aValue); }
SetHeight(const nsAString & aValue,mozilla::ErrorResult & rv)457   void SetHeight(const nsAString& aValue, mozilla::ErrorResult& rv) {
458     SetXULAttr(nsGkAtoms::height, aValue, rv);
459   }
GetMinWidth(DOMString & aValue)460   void GetMinWidth(DOMString& aValue) const {
461     GetXULAttr(nsGkAtoms::minwidth, aValue);
462   }
SetMinWidth(const nsAString & aValue,mozilla::ErrorResult & rv)463   void SetMinWidth(const nsAString& aValue, mozilla::ErrorResult& rv) {
464     SetXULAttr(nsGkAtoms::minwidth, aValue, rv);
465   }
GetMinHeight(DOMString & aValue)466   void GetMinHeight(DOMString& aValue) const {
467     GetXULAttr(nsGkAtoms::minheight, aValue);
468   }
SetMinHeight(const nsAString & aValue,mozilla::ErrorResult & rv)469   void SetMinHeight(const nsAString& aValue, mozilla::ErrorResult& rv) {
470     SetXULAttr(nsGkAtoms::minheight, aValue, rv);
471   }
GetMaxWidth(DOMString & aValue)472   void GetMaxWidth(DOMString& aValue) const {
473     GetXULAttr(nsGkAtoms::maxwidth, aValue);
474   }
SetMaxWidth(const nsAString & aValue,mozilla::ErrorResult & rv)475   void SetMaxWidth(const nsAString& aValue, mozilla::ErrorResult& rv) {
476     SetXULAttr(nsGkAtoms::maxwidth, aValue, rv);
477   }
GetMaxHeight(DOMString & aValue)478   void GetMaxHeight(DOMString& aValue) const {
479     GetXULAttr(nsGkAtoms::maxheight, aValue);
480   }
SetMaxHeight(const nsAString & aValue,mozilla::ErrorResult & rv)481   void SetMaxHeight(const nsAString& aValue, mozilla::ErrorResult& rv) {
482     SetXULAttr(nsGkAtoms::maxheight, aValue, rv);
483   }
GetTooltipText(DOMString & aValue)484   void GetTooltipText(DOMString& aValue) const {
485     GetXULAttr(nsGkAtoms::tooltiptext, aValue);
486   }
SetTooltipText(const nsAString & aValue,mozilla::ErrorResult & rv)487   void SetTooltipText(const nsAString& aValue, mozilla::ErrorResult& rv) {
488     SetXULAttr(nsGkAtoms::tooltiptext, aValue, rv);
489   }
GetSrc(DOMString & aValue)490   void GetSrc(DOMString& aValue) const { GetXULAttr(nsGkAtoms::src, aValue); }
SetSrc(const nsAString & aValue,mozilla::ErrorResult & rv)491   void SetSrc(const nsAString& aValue, mozilla::ErrorResult& rv) {
492     SetXULAttr(nsGkAtoms::src, aValue, rv);
493   }
494   nsIControllers* GetControllers(mozilla::ErrorResult& rv);
495   void Click(mozilla::dom::CallerType aCallerType);
496   MOZ_CAN_RUN_SCRIPT_BOUNDARY void DoCommand();
497   // Style() inherited from nsStyledElement
498 
GetScopeChainParent()499   nsINode* GetScopeChainParent() const override {
500     // For XUL, the parent is the parent element, if any
501     Element* parent = GetParentElement();
502     return parent ? parent : nsStyledElement::GetScopeChainParent();
503   }
504 
505   bool IsInteractiveHTMLContent() const override;
506 
507  protected:
508   ~nsXULElement();
509 
510   // This can be removed if EnsureContentsGenerated dies.
511   friend class nsNSElementTearoff;
512 
513   // Implementation methods
514   nsresult EnsureContentsGenerated(void) const;
515 
516   nsresult AddPopupListener(nsAtom* aName);
517 
518   /**
519    * Abandon our prototype linkage, and copy all attributes locally
520    */
521   nsresult MakeHeavyweight(nsXULPrototypeElement* aPrototype);
522 
523   virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
524                                  const nsAttrValueOrString* aValue,
525                                  bool aNotify) override;
526   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
527                                 const nsAttrValue* aValue,
528                                 const nsAttrValue* aOldValue,
529                                 nsIPrincipal* aSubjectPrincipal,
530                                 bool aNotify) override;
531 
532   virtual void UpdateEditableState(bool aNotify) override;
533 
534   virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
535                               const nsAString& aValue,
536                               nsIPrincipal* aMaybeScriptedPrincipal,
537                               nsAttrValue& aResult) override;
538 
539   virtual mozilla::EventListenerManager* GetEventListenerManagerForAttr(
540       nsAtom* aAttrName, bool* aDefer) override;
541 
542   /**
543    * Add a listener for the specified attribute, if appropriate.
544    */
545   void AddListenerForAttributeIfNeeded(const nsAttrName& aName);
546   void AddListenerForAttributeIfNeeded(nsAtom* aLocalName);
547 
548  protected:
549   void AddTooltipSupport();
550   void RemoveTooltipSupport();
551 
552   // Internal accessor. This shadows the 'Slots', and returns
553   // appropriate value.
Controllers()554   nsIControllers* Controllers() {
555     nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
556     return slots ? slots->mControllers.get() : nullptr;
557   }
558 
559   bool SupportsAccessKey() const;
560   void RegUnRegAccessKey(bool aDoReg) override;
561   bool BoolAttrIsTrue(nsAtom* aName) const;
562 
563   friend nsXULElement* NS_NewBasicXULElement(
564       already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
565 
566   friend nsresult NS_NewXULElement(mozilla::dom::Element** aResult,
567                                    mozilla::dom::NodeInfo* aNodeInfo,
568                                    mozilla::dom::FromParser aFromParser,
569                                    const nsAString* aIs);
570   friend void NS_TrustedNewXULElement(mozilla::dom::Element** aResult,
571                                       mozilla::dom::NodeInfo* aNodeInfo);
572 
573   static already_AddRefed<nsXULElement> CreateFromPrototype(
574       nsXULPrototypeElement* aPrototype, mozilla::dom::NodeInfo* aNodeInfo,
575       bool aIsScriptable, bool aIsRoot);
576 
577   virtual JSObject* WrapNode(JSContext* aCx,
578                              JS::Handle<JSObject*> aGivenProto) override;
579 
580   bool IsEventStoppedFromAnonymousScrollbar(mozilla::EventMessage aMessage);
581 
582   MOZ_CAN_RUN_SCRIPT
583   nsresult DispatchXULCommand(const mozilla::EventChainVisitor& aVisitor,
584                               nsAutoString& aCommand);
585 };
586 
587 #endif  // nsXULElement_h__
588