Bug 1807626 use an outline icon for speaker selection permissions r=pbz,desktop-theme...
[gecko.git] / dom / xul / nsXULElement.h
blob3666c38dd5fcf152400406c9fb957fc7664fc569
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/. */
6 /*
8 The base XUL element class and associates.
12 #ifndef nsXULElement_h__
13 #define nsXULElement_h__
15 #include <stdint.h>
16 #include <stdio.h>
17 #include "ErrorList.h"
18 #include "js/experimental/JSStencil.h"
19 #include "js/RootingAPI.h"
20 #include "js/SourceText.h"
21 #include "js/TracingAPI.h"
22 #include "js/TypeDecls.h"
23 #include "mozilla/AlreadyAddRefed.h"
24 #include "mozilla/Assertions.h"
25 #include "mozilla/Attributes.h"
26 #include "mozilla/BasicEvents.h"
27 #include "mozilla/RefPtr.h"
28 #include "mozilla/dom/DOMString.h"
29 #include "mozilla/dom/Element.h"
30 #include "mozilla/dom/FragmentOrElement.h"
31 #include "mozilla/dom/FromParser.h"
32 #include "mozilla/dom/NameSpaceConstants.h"
33 #include "mozilla/dom/NodeInfo.h"
34 #include "nsAtom.h"
35 #include "nsAttrName.h"
36 #include "nsAttrValue.h"
37 #include "nsCOMPtr.h"
38 #include "nsCaseTreatment.h"
39 #include "nsChangeHint.h"
40 #include "nsCycleCollectionParticipant.h"
41 #include "nsGkAtoms.h"
42 #include "nsIContent.h"
43 #include "nsINode.h"
44 #include "nsISupports.h"
45 #include "nsLiteralString.h"
46 #include "nsString.h"
47 #include "nsStyledElement.h"
48 #include "nsTArray.h"
49 #include "nsTLiteralString.h"
50 #include "nscore.h"
52 class JSObject;
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;
63 using nsPrototypeArray = nsTArray<RefPtr<nsXULPrototypeNode>>;
65 namespace JS {
66 class CompileOptions;
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
84 ////////////////////////////////////////////////////////////////////////
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
93 /**
95 A prototype attribute for an nsXULPrototypeElement.
99 class nsXULPrototypeAttribute {
100 public:
101 nsXULPrototypeAttribute()
102 : mName(nsGkAtoms::id) // XXX this is a hack, but names have to have a
103 // value
105 XUL_PROTOTYPE_ATTRIBUTE_METER(gNumAttributes);
106 MOZ_COUNT_CTOR(nsXULPrototypeAttribute);
109 ~nsXULPrototypeAttribute();
111 nsAttrName mName;
112 nsAttrValue mValue;
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 */
126 A prototype content model element that holds the "primordial" values
127 that have been parsed from the original XUL document.
131 class nsXULPrototypeNode {
132 public:
133 enum Type { eType_Element, eType_Script, eType_Text, eType_PI };
135 Type mType;
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;
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.
153 virtual void ReleaseSubtree() {}
155 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(nsXULPrototypeNode)
156 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsXULPrototypeNode)
158 protected:
159 explicit nsXULPrototypeNode(Type aType) : mType(aType) {}
160 virtual ~nsXULPrototypeNode() = default;
163 class nsXULPrototypeElement : public nsXULPrototypeNode {
164 public:
165 explicit nsXULPrototypeElement(mozilla::dom::NodeInfo* aNodeInfo = nullptr)
166 : nsXULPrototypeNode(eType_Element),
167 mNodeInfo(aNodeInfo),
168 mHasIdAttribute(false),
169 mHasClassAttribute(false),
170 mHasStyleAttribute(false),
171 mIsAtom(nullptr) {}
173 private:
174 virtual ~nsXULPrototypeElement() { Unlink(); }
176 public:
177 virtual void ReleaseSubtree() override {
178 for (int32_t i = mChildren.Length() - 1; i >= 0; i--) {
179 if (mChildren[i].get()) mChildren[i]->ReleaseSubtree();
181 mChildren.Clear();
182 nsXULPrototypeNode::ReleaseSubtree();
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;
193 nsresult SetAttrAt(uint32_t aPos, const nsAString& aValue,
194 nsIURI* aDocumentURI);
196 void Unlink();
198 nsPrototypeArray mChildren;
200 RefPtr<mozilla::dom::NodeInfo> mNodeInfo;
202 uint32_t mHasIdAttribute : 1;
203 uint32_t mHasClassAttribute : 1;
204 uint32_t mHasStyleAttribute : 1;
205 nsTArray<nsXULPrototypeAttribute> mAttributes; // [OWNER]
206 RefPtr<nsAtom> mIsAtom;
209 class nsXULPrototypeScript : public nsXULPrototypeNode {
210 public:
211 explicit nsXULPrototypeScript(uint32_t aLineNo);
213 private:
214 virtual ~nsXULPrototypeScript() = default;
216 void FillCompileOptions(JS::CompileOptions& options);
218 public:
219 virtual nsresult Serialize(
220 nsIObjectOutputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
221 const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) override;
222 nsresult SerializeOutOfLine(nsIObjectOutputStream* aStream,
223 nsXULPrototypeDocument* aProtoDoc);
224 virtual nsresult Deserialize(
225 nsIObjectInputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
226 nsIURI* aDocumentURI,
227 const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) override;
228 nsresult DeserializeOutOfLine(nsIObjectInputStream* aInput,
229 nsXULPrototypeDocument* aProtoDoc);
231 template <typename Unit>
232 nsresult Compile(const Unit* aText, size_t aTextLength,
233 JS::SourceOwnership aOwnership, nsIURI* aURI,
234 uint32_t aLineNo, mozilla::dom::Document* aDocument,
235 nsIOffThreadScriptReceiver* aOffThreadReceiver = nullptr);
237 void Set(JS::Stencil* aStencil);
239 bool HasStencil() { return mStencil; }
241 JS::Stencil* GetStencil() { return mStencil.get(); }
243 nsresult InstantiateScript(JSContext* aCx,
244 JS::MutableHandle<JSScript*> aScript);
246 nsCOMPtr<nsIURI> mSrcURI;
247 uint32_t mLineNo;
248 bool mSrcLoading;
249 bool mOutOfLine;
250 mozilla::dom::PrototypeDocumentContentSink*
251 mSrcLoadWaiters; // [OWNER] but not COMPtr
252 private:
253 RefPtr<JS::Stencil> mStencil;
256 class nsXULPrototypeText : public nsXULPrototypeNode {
257 public:
258 nsXULPrototypeText() : nsXULPrototypeNode(eType_Text) {}
260 private:
261 virtual ~nsXULPrototypeText() = default;
263 public:
264 virtual nsresult Serialize(
265 nsIObjectOutputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
266 const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) override;
267 virtual nsresult Deserialize(
268 nsIObjectInputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
269 nsIURI* aDocumentURI,
270 const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) override;
272 nsString mValue;
275 class nsXULPrototypePI : public nsXULPrototypeNode {
276 public:
277 nsXULPrototypePI() : nsXULPrototypeNode(eType_PI) {}
279 private:
280 virtual ~nsXULPrototypePI() = default;
282 public:
283 virtual nsresult Serialize(
284 nsIObjectOutputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
285 const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) override;
286 virtual nsresult Deserialize(
287 nsIObjectInputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
288 nsIURI* aDocumentURI,
289 const nsTArray<RefPtr<mozilla::dom::NodeInfo>>* aNodeInfos) override;
291 nsString mTarget;
292 nsString mData;
295 ////////////////////////////////////////////////////////////////////////
299 The XUL element.
303 #define XUL_ELEMENT_FLAG_BIT(n_) \
304 NODE_FLAG_BIT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_))
306 // XUL element specific bits
307 enum {
308 XUL_ELEMENT_HAS_CONTENTMENU_LISTENER = XUL_ELEMENT_FLAG_BIT(0),
309 XUL_ELEMENT_HAS_POPUP_LISTENER = XUL_ELEMENT_FLAG_BIT(1)
312 ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
314 #undef XUL_ELEMENT_FLAG_BIT
316 class nsXULElement : public nsStyledElement {
317 protected:
318 using Document = mozilla::dom::Document;
320 // Use Construct to construct elements instead of this constructor.
321 explicit nsXULElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
323 public:
324 using Element::Blur;
325 using Element::Focus;
327 static nsresult CreateFromPrototype(nsXULPrototypeElement* aPrototype,
328 Document* aDocument, bool aIsScriptable,
329 bool aIsRoot,
330 mozilla::dom::Element** aResult);
332 // This is the constructor for nsXULElements.
333 static nsXULElement* Construct(
334 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
336 NS_IMPL_FROMNODE(nsXULElement, kNameSpaceID_XUL)
338 // nsISupports
339 NS_DECL_ISUPPORTS_INHERITED
340 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULElement, nsStyledElement)
342 // This doesn't work on XUL elements! You probably want
343 // GetXULBoolAttr(nsGkAtoms::disabled) or so.
344 // TODO(emilio): Maybe we should unify HTML and XUL here.
345 bool IsDisabled() const = delete;
347 // nsINode
348 void GetEventTargetParent(mozilla::EventChainPreVisitor& aVisitor) override;
349 MOZ_CAN_RUN_SCRIPT_BOUNDARY
350 virtual nsresult PreHandleEvent(
351 mozilla::EventChainVisitor& aVisitor) override;
352 // nsIContent
353 virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
354 virtual void UnbindFromTree(bool aNullParent) override;
355 virtual void DestroyContent() override;
356 virtual void DoneAddingChildren(bool aHaveNotified) override;
358 #ifdef MOZ_DOM_LIST
359 virtual void List(FILE* out, int32_t aIndent) const override;
360 virtual void DumpContent(FILE* out, int32_t aIndent,
361 bool aDumpAll) const override {}
362 #endif
364 MOZ_CAN_RUN_SCRIPT bool HasMenu();
365 MOZ_CAN_RUN_SCRIPT void OpenMenu(bool aOpenFlag);
367 MOZ_CAN_RUN_SCRIPT
368 virtual mozilla::Result<bool, nsresult> PerformAccesskey(
369 bool aKeyCausesActivation, bool aIsTrustedEvent) override;
370 MOZ_CAN_RUN_SCRIPT void ClickWithInputSource(uint16_t aInputSource,
371 bool aIsTrustedEvent);
373 bool IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse) override;
375 NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
377 virtual nsresult Clone(mozilla::dom::NodeInfo*,
378 nsINode** aResult) const override;
380 virtual bool IsEventAttributeNameInternal(nsAtom* aName) override;
382 using DOMString = mozilla::dom::DOMString;
383 void GetXULAttr(nsAtom* aName, DOMString& aResult) const {
384 GetAttr(aName, aResult);
386 void SetXULAttr(nsAtom* aName, const nsAString& aValue,
387 mozilla::ErrorResult& aError) {
388 SetAttr(aName, aValue, aError);
390 bool GetXULBoolAttr(nsAtom* aName) const {
391 return AttrValueIs(kNameSpaceID_None, aName, u"true"_ns, eCaseMatters);
393 void SetXULBoolAttr(nsAtom* aName, bool aValue,
394 mozilla::ErrorResult& aError) {
395 if (aValue) {
396 SetAttr(aName, u"true"_ns, aError);
397 } else {
398 UnsetAttr(aName, aError);
402 // WebIDL API
403 bool Autofocus() const { return BoolAttrIsTrue(nsGkAtoms::autofocus); }
404 void SetAutofocus(bool aAutofocus, ErrorResult& aRv) {
405 SetXULBoolAttr(nsGkAtoms::autofocus, aAutofocus, aRv);
407 bool Hidden() const { return BoolAttrIsTrue(nsGkAtoms::hidden); }
408 void SetHidden(bool aHidden) {
409 SetXULBoolAttr(nsGkAtoms::hidden, aHidden, mozilla::IgnoreErrors());
411 bool Collapsed() const { return BoolAttrIsTrue(nsGkAtoms::collapsed); }
412 void SetCollapsed(bool aCollapsed) {
413 SetXULBoolAttr(nsGkAtoms::collapsed, aCollapsed, mozilla::IgnoreErrors());
415 void GetObserves(DOMString& aValue) const {
416 GetXULAttr(nsGkAtoms::observes, aValue);
418 void SetObserves(const nsAString& aValue, mozilla::ErrorResult& rv) {
419 SetXULAttr(nsGkAtoms::observes, aValue, rv);
421 void GetMenu(DOMString& aValue) const { GetXULAttr(nsGkAtoms::menu, aValue); }
422 void SetMenu(const nsAString& aValue, mozilla::ErrorResult& rv) {
423 SetXULAttr(nsGkAtoms::menu, aValue, rv);
425 void GetContextMenu(DOMString& aValue) {
426 GetXULAttr(nsGkAtoms::contextmenu, aValue);
428 void SetContextMenu(const nsAString& aValue, mozilla::ErrorResult& rv) {
429 SetXULAttr(nsGkAtoms::contextmenu, aValue, rv);
431 void GetTooltip(DOMString& aValue) const {
432 GetXULAttr(nsGkAtoms::tooltip, aValue);
434 void SetTooltip(const nsAString& aValue, mozilla::ErrorResult& rv) {
435 SetXULAttr(nsGkAtoms::tooltip, aValue, rv);
437 void GetTooltipText(DOMString& aValue) const {
438 GetXULAttr(nsGkAtoms::tooltiptext, aValue);
440 void SetTooltipText(const nsAString& aValue, mozilla::ErrorResult& rv) {
441 SetXULAttr(nsGkAtoms::tooltiptext, aValue, rv);
443 void GetSrc(DOMString& aValue) const { GetXULAttr(nsGkAtoms::src, aValue); }
444 void SetSrc(const nsAString& aValue, mozilla::ErrorResult& rv) {
445 SetXULAttr(nsGkAtoms::src, aValue, rv);
447 nsIControllers* GetControllers(mozilla::ErrorResult& rv);
448 // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
449 MOZ_CAN_RUN_SCRIPT_BOUNDARY void Click(mozilla::dom::CallerType aCallerType);
450 // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
451 MOZ_CAN_RUN_SCRIPT_BOUNDARY void DoCommand();
452 // Style() inherited from nsStyledElement
454 nsINode* GetScopeChainParent() const override {
455 // For XUL, the parent is the parent element, if any
456 Element* parent = GetParentElement();
457 return parent ? parent : nsStyledElement::GetScopeChainParent();
460 bool IsInteractiveHTMLContent() const override;
462 protected:
463 ~nsXULElement();
465 // This can be removed if EnsureContentsGenerated dies.
466 friend class nsNSElementTearoff;
468 // Implementation methods
469 nsresult EnsureContentsGenerated(void) const;
471 nsresult AddPopupListener(nsAtom* aName);
474 * Abandon our prototype linkage, and copy all attributes locally
476 nsresult MakeHeavyweight(nsXULPrototypeElement* aPrototype);
478 void BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
479 const nsAttrValue* aValue, bool aNotify) override;
480 void AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
481 const nsAttrValue* aValue, const nsAttrValue* aOldValue,
482 nsIPrincipal* aSubjectPrincipal, bool aNotify) override;
484 void UpdateEditableState(bool aNotify) override;
486 bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
487 const nsAString& aValue,
488 nsIPrincipal* aMaybeScriptedPrincipal,
489 nsAttrValue& aResult) override;
491 mozilla::EventListenerManager* GetEventListenerManagerForAttr(
492 nsAtom* aAttrName, bool* aDefer) override;
495 * Add a listener for the specified attribute, if appropriate.
497 void AddListenerForAttributeIfNeeded(const nsAttrName& aName);
498 void AddListenerForAttributeIfNeeded(nsAtom* aLocalName);
500 protected:
501 void AddTooltipSupport();
502 void RemoveTooltipSupport();
504 // Internal accessor. This shadows the 'Slots', and returns
505 // appropriate value.
506 nsIControllers* Controllers() {
507 nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
508 return slots ? slots->mControllers.get() : nullptr;
511 bool SupportsAccessKey() const;
512 void RegUnRegAccessKey(bool aDoReg) override;
513 bool BoolAttrIsTrue(nsAtom* aName) const;
515 friend nsXULElement* NS_NewBasicXULElement(
516 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
518 friend nsresult NS_NewXULElement(mozilla::dom::Element** aResult,
519 mozilla::dom::NodeInfo* aNodeInfo,
520 mozilla::dom::FromParser aFromParser,
521 const nsAString* aIs);
522 friend void NS_TrustedNewXULElement(mozilla::dom::Element** aResult,
523 mozilla::dom::NodeInfo* aNodeInfo);
525 static already_AddRefed<nsXULElement> CreateFromPrototype(
526 nsXULPrototypeElement* aPrototype, mozilla::dom::NodeInfo* aNodeInfo,
527 bool aIsScriptable, bool aIsRoot);
529 JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
531 bool IsEventStoppedFromAnonymousScrollbar(mozilla::EventMessage aMessage);
533 MOZ_CAN_RUN_SCRIPT
534 nsresult DispatchXULCommand(const mozilla::EventChainVisitor& aVisitor,
535 nsAutoString& aCommand);
538 #endif // nsXULElement_h__