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 #ifndef nsXULContentSink_h__ 7 #define nsXULContentSink_h__ 8 9 #include "mozilla/Attributes.h" 10 #include "nsIExpatSink.h" 11 #include "nsIWeakReferenceUtils.h" 12 #include "nsIXMLContentSink.h" 13 #include "nsNodeInfoManager.h" 14 #include "nsXULElement.h" 15 #include "nsIDTD.h" 16 17 class nsIScriptSecurityManager; 18 class nsAttrName; 19 class nsXULPrototypeDocument; 20 class nsXULPrototypeElement; 21 class nsXULPrototypeNode; 22 23 class XULContentSinkImpl final : public nsIXMLContentSink, public nsIExpatSink { 24 public: 25 XULContentSinkImpl(); 26 27 // nsISupports 28 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 29 NS_DECL_NSIEXPATSINK 30 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(XULContentSinkImpl,nsIXMLContentSink)31 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(XULContentSinkImpl, 32 nsIXMLContentSink) 33 34 // nsIContentSink 35 NS_IMETHOD WillParse(void) override { return NS_OK; } 36 NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode) override; 37 NS_IMETHOD DidBuildModel(bool aTerminated) override; 38 NS_IMETHOD WillInterrupt(void) override; 39 NS_IMETHOD WillResume(void) override; 40 NS_IMETHOD SetParser(nsParserBase* aParser) override; FlushPendingNotifications(mozilla::FlushType aType)41 virtual void FlushPendingNotifications(mozilla::FlushType aType) override {} 42 virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override; 43 virtual nsISupports* GetTarget() override; 44 45 /** 46 * Initialize the content sink, giving it a document with which to communicate 47 * with the outside world, and an nsXULPrototypeDocument to build. 48 */ 49 nsresult Init(mozilla::dom::Document* aDocument, 50 nsXULPrototypeDocument* aPrototype); 51 52 protected: 53 virtual ~XULContentSinkImpl(); 54 55 // pseudo-constants 56 char16_t* mText; 57 int32_t mTextLength; 58 int32_t mTextSize; 59 bool mConstrainSize; 60 61 nsresult AddAttributes(const char16_t** aAttributes, const uint32_t aAttrLen, 62 nsXULPrototypeElement* aElement); 63 64 nsresult OpenRoot(const char16_t** aAttributes, const uint32_t aAttrLen, 65 mozilla::dom::NodeInfo* aNodeInfo); 66 67 nsresult OpenTag(const char16_t** aAttributes, const uint32_t aAttrLen, 68 const uint32_t aLineNumber, 69 mozilla::dom::NodeInfo* aNodeInfo); 70 71 // If OpenScript returns NS_OK and after it returns our state is eInScript, 72 // that means that we created a prototype script and stuck it on 73 // mContextStack. If NS_OK is returned but the state is still 74 // eInDocumentElement then we didn't create a prototype script (e.g. the 75 // script had an unknown type), and the caller should create a prototype 76 // element. 77 nsresult OpenScript(const char16_t** aAttributes, const uint32_t aLineNumber); 78 79 static bool IsDataInBuffer(char16_t* aBuffer, int32_t aLength); 80 81 // Text management 82 nsresult FlushText(bool aCreateTextNode = true); 83 nsresult AddText(const char16_t* aText, int32_t aLength); 84 85 RefPtr<nsNodeInfoManager> mNodeInfoManager; 86 87 nsresult NormalizeAttributeString(const char16_t* aExpatName, 88 nsAttrName& aName); 89 90 public: 91 enum State { eInProlog, eInDocumentElement, eInScript, eInEpilog }; 92 93 protected: 94 State mState; 95 96 // content stack management 97 class ContextStack { 98 protected: 99 struct Entry { 100 RefPtr<nsXULPrototypeNode> mNode; 101 // a LOT of nodes have children; preallocate for 8 102 nsPrototypeArray mChildren; 103 State mState; 104 Entry* mNext; EntryEntry105 Entry(RefPtr<nsXULPrototypeNode>&& aNode, State aState, Entry* aNext) 106 : mNode(std::move(aNode)), 107 mChildren(8), 108 mState(aState), 109 mNext(aNext) {} 110 }; 111 112 Entry* mTop; 113 int32_t mDepth; 114 115 public: 116 ContextStack(); 117 ~ContextStack(); 118 Depth()119 int32_t Depth() { return mDepth; } 120 121 void Push(RefPtr<nsXULPrototypeNode>&& aNode, State aState); 122 nsresult Pop(State* aState); 123 124 nsresult GetTopNode(RefPtr<nsXULPrototypeNode>& aNode); 125 nsresult GetTopChildren(nsPrototypeArray** aChildren); 126 127 void Clear(); 128 129 void Traverse(nsCycleCollectionTraversalCallback& aCallback); 130 }; 131 132 friend class ContextStack; 133 ContextStack mContextStack; 134 135 nsWeakPtr mDocument; // [OWNER] 136 nsCOMPtr<nsIURI> mDocumentURL; // [OWNER] 137 138 RefPtr<nsXULPrototypeDocument> mPrototype; // [OWNER] 139 140 RefPtr<nsParserBase> mParser; 141 nsCOMPtr<nsIScriptSecurityManager> mSecMan; 142 }; 143 144 #endif /* nsXULContentSink_h__ */ 145