|
1 /* -*- Mode: C++; tab-width: 2; 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 /* Here is the list, from beppe and glazman: |
|
7 href >> A, AREA, BASE, LINK |
|
8 src >> FRAME, IFRAME, IMG, INPUT, SCRIPT |
|
9 <META http-equiv="refresh" content="3,http://www.acme.com/intro.html"> |
|
10 longdesc >> FRAME, IFRAME, IMG |
|
11 usemap >> IMG, INPUT, OBJECT |
|
12 action >> FORM |
|
13 background >> BODY |
|
14 codebase >> OBJECT, APPLET |
|
15 classid >> OBJECT |
|
16 data >> OBJECT |
|
17 cite >> BLOCKQUOTE, DEL, INS, Q |
|
18 profile >> HEAD |
|
19 ARCHIVE attribute on APPLET ; warning, it contains a list of URIs. |
|
20 |
|
21 Easier way of organizing the list: |
|
22 a: href |
|
23 area: href |
|
24 base: href |
|
25 body: background |
|
26 blockquote: cite (not normally rewritable) |
|
27 link: href |
|
28 frame: src, longdesc |
|
29 iframe: src, longdesc |
|
30 input: src, usemap |
|
31 form: action |
|
32 img: src, longdesc, usemap |
|
33 script: src |
|
34 applet: codebase, archive <list> |
|
35 object: codebase, data, classid, usemap |
|
36 head: profile |
|
37 del: cite |
|
38 ins: cite |
|
39 q: cite |
|
40 */ |
|
41 |
|
42 /* Here is how to open a channel for testing |
|
43 (from embed/qa/testembed/Tests.cpp): |
|
44 |
|
45 nsCOMPtr<nsIChannel> theChannel; |
|
46 nsCString uri; |
|
47 nsCOMPtr<nsIURI> theURI; |
|
48 rv = NS_NewURI(getter_AddRefs(theURI), theSpec); |
|
49 if (!theURI) |
|
50 error; |
|
51 rv = NS_OpenURI(getter_AddRefs(theChannel), theURI, nullptr, theLoadGroup); |
|
52 if (!theChannel) |
|
53 error; |
|
54 nsCOMPtr<nsILoadGroup> theLoadGroup(do_CreateInstance(NS_LOADGROUP_CONTRACTID)); |
|
55 if (!theLoadGroup) |
|
56 error; |
|
57 nsCOMPtr<nsIStreamListener> listener(static_cast<nsIStreamListener*>(qaBrowserImpl)); |
|
58 //nsCOMPtr<nsIWeakReference> thisListener(do_GetWeakReference(listener)); |
|
59 //qaWebBrowser->AddWebBrowserListener(thisListener, NS_GET_IID(nsIStreamListener)); |
|
60 |
|
61 // this calls nsIStreamListener::OnDataAvailable() |
|
62 rv = theChannel->AsyncOpen(listener, nullptr); |
|
63 |
|
64 nsCOMPtr<nsIRequest> theRequest = do_QueryInterface(theChannel); |
|
65 // Now we can do things on nsIRequest (like what?) |
|
66 */ |
|
67 |
|
68 #include "mozilla/mozalloc.h" |
|
69 #include "nsAString.h" |
|
70 #include "nsDebug.h" |
|
71 #include "nsError.h" |
|
72 #include "nsHTMLURIRefObject.h" |
|
73 #include "nsID.h" |
|
74 #include "nsIDOMAttr.h" |
|
75 #include "nsIDOMElement.h" |
|
76 #include "nsIDOMMozNamedAttrMap.h" |
|
77 #include "nsIDOMNode.h" |
|
78 #include "nsISupportsUtils.h" |
|
79 #include "nsString.h" |
|
80 |
|
81 // String classes change too often and I can't keep up. |
|
82 // Set this macro to this week's approved case-insensitive compare routine. |
|
83 #define MATCHES(tagName, str) tagName.EqualsIgnoreCase(str) |
|
84 |
|
85 nsHTMLURIRefObject::nsHTMLURIRefObject() |
|
86 { |
|
87 mCurAttrIndex = mAttributeCnt = 0; |
|
88 } |
|
89 |
|
90 nsHTMLURIRefObject::~nsHTMLURIRefObject() |
|
91 { |
|
92 } |
|
93 |
|
94 //Interfaces for addref and release and queryinterface |
|
95 NS_IMPL_ISUPPORTS(nsHTMLURIRefObject, nsIURIRefObject) |
|
96 |
|
97 NS_IMETHODIMP |
|
98 nsHTMLURIRefObject::Reset() |
|
99 { |
|
100 mCurAttrIndex = 0; |
|
101 return NS_OK; |
|
102 } |
|
103 |
|
104 NS_IMETHODIMP |
|
105 nsHTMLURIRefObject::GetNextURI(nsAString & aURI) |
|
106 { |
|
107 NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED); |
|
108 |
|
109 nsAutoString tagName; |
|
110 nsresult rv = mNode->GetNodeName(tagName); |
|
111 NS_ENSURE_SUCCESS(rv, rv); |
|
112 |
|
113 // Loop over attribute list: |
|
114 if (!mAttributes) |
|
115 { |
|
116 nsCOMPtr<nsIDOMElement> element (do_QueryInterface(mNode)); |
|
117 NS_ENSURE_TRUE(element, NS_ERROR_INVALID_ARG); |
|
118 |
|
119 mCurAttrIndex = 0; |
|
120 element->GetAttributes(getter_AddRefs(mAttributes)); |
|
121 NS_ENSURE_TRUE(mAttributes, NS_ERROR_NOT_INITIALIZED); |
|
122 |
|
123 rv = mAttributes->GetLength(&mAttributeCnt); |
|
124 NS_ENSURE_SUCCESS(rv, rv); |
|
125 NS_ENSURE_TRUE(mAttributeCnt, NS_ERROR_FAILURE); |
|
126 mCurAttrIndex = 0; |
|
127 } |
|
128 #ifdef DEBUG_akkana |
|
129 printf("Looking at tag '%s'\n", |
|
130 NS_LossyConvertUTF16toASCII(tagName).get()); |
|
131 #endif |
|
132 while (mCurAttrIndex < mAttributeCnt) |
|
133 { |
|
134 nsCOMPtr<nsIDOMAttr> attrNode; |
|
135 rv = mAttributes->Item(mCurAttrIndex++, getter_AddRefs(attrNode)); |
|
136 NS_ENSURE_SUCCESS(rv, rv); |
|
137 NS_ENSURE_ARG_POINTER(attrNode); |
|
138 nsString curAttr; |
|
139 rv = attrNode->GetName(curAttr); |
|
140 NS_ENSURE_SUCCESS(rv, rv); |
|
141 |
|
142 // href >> A, AREA, BASE, LINK |
|
143 #ifdef DEBUG_akkana |
|
144 printf("Trying to match attribute '%s'\n", |
|
145 NS_LossyConvertUTF16toASCII(curAttr).get()); |
|
146 #endif |
|
147 if (MATCHES(curAttr, "href")) |
|
148 { |
|
149 if (!MATCHES(tagName, "a") && !MATCHES(tagName, "area") |
|
150 && !MATCHES(tagName, "base") && !MATCHES(tagName, "link")) |
|
151 continue; |
|
152 rv = attrNode->GetValue(aURI); |
|
153 NS_ENSURE_SUCCESS(rv, rv); |
|
154 nsString uri (aURI); |
|
155 // href pointing to a named anchor doesn't count |
|
156 if (aURI.First() != char16_t('#')) |
|
157 return NS_OK; |
|
158 aURI.Truncate(); |
|
159 return NS_ERROR_INVALID_ARG; |
|
160 } |
|
161 // src >> FRAME, IFRAME, IMG, INPUT, SCRIPT |
|
162 else if (MATCHES(curAttr, "src")) |
|
163 { |
|
164 if (!MATCHES(tagName, "img") |
|
165 && !MATCHES(tagName, "frame") && !MATCHES(tagName, "iframe") |
|
166 && !MATCHES(tagName, "input") && !MATCHES(tagName, "script")) |
|
167 continue; |
|
168 return attrNode->GetValue(aURI); |
|
169 } |
|
170 //<META http-equiv="refresh" content="3,http://www.acme.com/intro.html"> |
|
171 else if (MATCHES(curAttr, "content")) |
|
172 { |
|
173 if (!MATCHES(tagName, "meta")) |
|
174 continue; |
|
175 } |
|
176 // longdesc >> FRAME, IFRAME, IMG |
|
177 else if (MATCHES(curAttr, "longdesc")) |
|
178 { |
|
179 if (!MATCHES(tagName, "img") |
|
180 && !MATCHES(tagName, "frame") && !MATCHES(tagName, "iframe")) |
|
181 continue; |
|
182 } |
|
183 // usemap >> IMG, INPUT, OBJECT |
|
184 else if (MATCHES(curAttr, "usemap")) |
|
185 { |
|
186 if (!MATCHES(tagName, "img") |
|
187 && !MATCHES(tagName, "input") && !MATCHES(tagName, "object")) |
|
188 continue; |
|
189 } |
|
190 // action >> FORM |
|
191 else if (MATCHES(curAttr, "action")) |
|
192 { |
|
193 if (!MATCHES(tagName, "form")) |
|
194 continue; |
|
195 } |
|
196 // background >> BODY |
|
197 else if (MATCHES(curAttr, "background")) |
|
198 { |
|
199 if (!MATCHES(tagName, "body")) |
|
200 continue; |
|
201 } |
|
202 // codebase >> OBJECT, APPLET |
|
203 else if (MATCHES(curAttr, "codebase")) |
|
204 { |
|
205 if (!MATCHES(tagName, "meta")) |
|
206 continue; |
|
207 } |
|
208 // classid >> OBJECT |
|
209 else if (MATCHES(curAttr, "classid")) |
|
210 { |
|
211 if (!MATCHES(tagName, "object")) |
|
212 continue; |
|
213 } |
|
214 // data >> OBJECT |
|
215 else if (MATCHES(curAttr, "data")) |
|
216 { |
|
217 if (!MATCHES(tagName, "object")) |
|
218 continue; |
|
219 } |
|
220 // cite >> BLOCKQUOTE, DEL, INS, Q |
|
221 else if (MATCHES(curAttr, "cite")) |
|
222 { |
|
223 if (!MATCHES(tagName, "blockquote") && !MATCHES(tagName, "q") |
|
224 && !MATCHES(tagName, "del") && !MATCHES(tagName, "ins")) |
|
225 continue; |
|
226 } |
|
227 // profile >> HEAD |
|
228 else if (MATCHES(curAttr, "profile")) |
|
229 { |
|
230 if (!MATCHES(tagName, "head")) |
|
231 continue; |
|
232 } |
|
233 // archive attribute on APPLET; warning, it contains a list of URIs. |
|
234 else if (MATCHES(curAttr, "archive")) |
|
235 { |
|
236 if (!MATCHES(tagName, "applet")) |
|
237 continue; |
|
238 } |
|
239 } |
|
240 // Return a code to indicate that there are no more, |
|
241 // to distinguish that case from real errors. |
|
242 return NS_ERROR_NOT_AVAILABLE; |
|
243 } |
|
244 |
|
245 NS_IMETHODIMP |
|
246 nsHTMLURIRefObject::RewriteAllURIs(const nsAString & aOldPat, |
|
247 const nsAString & aNewPat, |
|
248 bool aMakeRel) |
|
249 { |
|
250 #ifdef DEBUG_akkana |
|
251 printf("Can't rewrite URIs yet\n"); |
|
252 #endif |
|
253 return NS_ERROR_NOT_IMPLEMENTED; |
|
254 } |
|
255 |
|
256 NS_IMETHODIMP |
|
257 nsHTMLURIRefObject::GetNode(nsIDOMNode** aNode) |
|
258 { |
|
259 NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED); |
|
260 NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER); |
|
261 *aNode = mNode.get(); |
|
262 NS_ADDREF(*aNode); |
|
263 return NS_OK; |
|
264 } |
|
265 |
|
266 NS_IMETHODIMP |
|
267 nsHTMLURIRefObject::SetNode(nsIDOMNode *aNode) |
|
268 { |
|
269 mNode = aNode; |
|
270 nsAutoString dummyURI; |
|
271 if (NS_SUCCEEDED(GetNextURI(dummyURI))) |
|
272 { |
|
273 mCurAttrIndex = 0; // Reset so we'll get the first node next time |
|
274 return NS_OK; |
|
275 } |
|
276 |
|
277 // If there weren't any URIs in the attributes, |
|
278 // then don't accept this node. |
|
279 mNode = 0; |
|
280 return NS_ERROR_INVALID_ARG; |
|
281 } |
|
282 |
|
283 nsresult NS_NewHTMLURIRefObject(nsIURIRefObject** aResult, nsIDOMNode* aNode) |
|
284 { |
|
285 nsHTMLURIRefObject* refObject = new nsHTMLURIRefObject(); |
|
286 nsresult rv = refObject->SetNode(aNode); |
|
287 if (NS_FAILED(rv)) { |
|
288 *aResult = 0; |
|
289 delete refObject; |
|
290 return rv; |
|
291 } |
|
292 return refObject->QueryInterface(NS_GET_IID(nsIURIRefObject), |
|
293 (void**)aResult); |
|
294 } |
|
295 |