Disable XBL. The loadBindings call was taking 0.1-0.25%. While I know how to get...
[WebKit-https.git] / WebCore / khtml / xbl / xbl_binding.cpp
1 #ifndef KHTML_NO_XBL
2
3 #include <kurl.h>
4 #include "xbl_protobinding.h"
5 #include "xbl_binding.h"
6 #include "xbl_docimpl.h"
7 #include "xbl_binding_manager.h"
8 #include "misc/loader.h"
9
10 using DOM::DOMString;
11 using DOM::ElementImpl;
12 using DOM::DocumentImpl;
13 using khtml::CachedXBLDocument;
14
15 namespace XBL
16 {
17
18 XBLBindingChain::XBLBindingChain(ElementImpl* elt, const DOMString& uri, bool isStyleChain)
19 :m_uri(uri), m_element(elt), m_previousChain(0), m_nextChain(0), m_isStyleChain(isStyleChain), 
20  m_markedForDeath(false)
21 {
22     m_binding = new XBLBinding(this, uri);
23 }
24
25 XBLBindingChain::~XBLBindingChain()
26 {
27     delete m_binding;
28     delete m_nextChain;
29 }
30
31 XBLBindingChain* XBLBindingChain::firstStyleBindingChain()
32 {
33     if (m_isStyleChain)
34         return this;
35     if (m_nextChain)
36         return m_nextChain->firstStyleBindingChain();
37     return 0;
38 }
39
40 XBLBindingChain* XBLBindingChain::lastBindingChain()
41 {
42     if (m_nextChain)
43         return m_nextChain->lastBindingChain();
44     return this;
45 }
46
47 void XBLBindingChain::insertBindingChain(XBLBindingChain* bindingChain)
48 {
49     if (m_nextChain) {
50         m_nextChain->setPreviousBindingChain(bindingChain);
51         bindingChain->setNextBindingChain(m_nextChain);
52     }
53     
54     if (bindingChain)
55         bindingChain->setPreviousBindingChain(this);
56     setNextBindingChain(bindingChain);
57 }
58
59 void XBLBindingChain::markForDeath()
60 {
61     m_markedForDeath = true;
62     if (m_nextChain && m_isStyleChain)
63         m_nextChain->markForDeath();
64
65     // FIXME: Schedule a timer that will fire as soon as possible and destroy the binding.
66 }
67
68 bool XBLBindingChain::loaded() const
69 {
70     if (m_binding && !m_binding->loaded())
71         return false;
72     if (m_nextChain)
73         return m_nextChain->loaded();
74     return true;
75 }
76
77 bool XBLBindingChain::hasStylesheets() const
78 {
79     if (m_binding && m_binding->hasStylesheets())
80         return true;
81     if (m_nextChain)
82         return m_nextChain->hasStylesheets();
83     return false;
84 }
85
86 void XBLBindingChain::failed()
87 {
88     delete m_binding;
89     m_binding = 0;
90     
91     element()->getDocument()->bindingManager()->checkLoadState(element());
92 }
93
94 // ==========================================================================================
95
96 XBLBinding::XBLBinding(XBLBindingChain* ch, const DOMString& uri, XBLBinding* derivedBinding)
97 :m_chain(ch), m_xblDocument(0), m_prototype(0), m_previousBinding(0), m_nextBinding(0)
98 {
99     if (derivedBinding)
100         derivedBinding->setNextBinding(this);
101     setPreviousBinding(derivedBinding);
102     
103     // Parse the URL into a document URI and a binding id.  Kick off the load of
104     // the XBL document here, and cache the id that we hope to find once the document
105     // has loaded in m_id.
106     DOMString docURL = uri;
107     int hashIndex = uri.find('#');
108     if (hashIndex != -1) {
109         QString url = uri.string();
110         docURL = url.left(hashIndex);
111         if (int(url.length()) > hashIndex+1)
112             m_id = url.right(url.length()-hashIndex-1);
113     }
114     else
115         m_id = "_xbl_first_binding";
116     
117     // Now kick off the load of the XBL document.
118     DocumentImpl* doc = chain()->element()->getDocument();
119     m_xblDocument = doc->docLoader()->requestXBLDocument(docURL);
120     if (m_xblDocument)
121         m_xblDocument->ref(this);
122 }
123
124 XBLBinding::~XBLBinding()
125 {
126     delete m_nextBinding;
127     if (m_xblDocument)
128         m_xblDocument->deref(this);
129 }
130
131 bool XBLBinding::loaded() const
132 {
133     // If our prototype document hasn't loaded, then we aren't ready yet.
134     if (!m_prototype)
135         return false;
136     
137     // FIXME: If all our resources haven't loaded, then we aren't ready.
138     
139     // If our base binding hasn't loaded, then we also aren't ready yet.
140     if (m_nextBinding && !m_nextBinding->loaded())
141         return false;
142
143     // We're ready.
144     return true;
145 }
146
147 void XBLBinding::setXBLDocument(const DOMString& url, XBLDocumentImpl* doc) 
148 {
149     // Locate the prototype binding.  If it doesn't exist in the XBLDocument, then the entire binding
150     // chain is considered invalid and should be destroyed.
151     if (m_id == "_xbl_first_binding") {
152         // FIXME: Obtain the ID of the first binding by examining the DOM.
153     }
154     
155     // Obtain our prototype from the XBL document.
156     m_prototype = doc->prototypeBinding(m_id);
157     
158     if (!m_prototype)
159         return chain()->failed(); // This binding chain failed to load. Discard the chain.
160     
161     // See if we have an "extends" attribute.  If so, load that binding.
162     DOMString extends = m_prototype->element()->getAttribute("extends");
163     if (!extends.isEmpty()) {
164         // FIXME: Add support for : extension for built-in types, e.g., "html:img".
165         // Resolve to an absolute URL.
166         new XBLBinding(chain(), 
167                        KURL(m_prototype->document()->baseURL(), extends.string()).url(),
168                        this);
169         return;
170     }
171     
172     chain()->element()->getDocument()->bindingManager()->checkLoadState(chain()->element());
173 }
174
175 }
176
177 #endif // KHTML_NO_XBL
178