michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* Here is the list, from beppe and glazman: michael@0: href >> A, AREA, BASE, LINK michael@0: src >> FRAME, IFRAME, IMG, INPUT, SCRIPT michael@0: michael@0: longdesc >> FRAME, IFRAME, IMG michael@0: usemap >> IMG, INPUT, OBJECT michael@0: action >> FORM michael@0: background >> BODY michael@0: codebase >> OBJECT, APPLET michael@0: classid >> OBJECT michael@0: data >> OBJECT michael@0: cite >> BLOCKQUOTE, DEL, INS, Q michael@0: profile >> HEAD michael@0: ARCHIVE attribute on APPLET ; warning, it contains a list of URIs. michael@0: michael@0: Easier way of organizing the list: michael@0: a: href michael@0: area: href michael@0: base: href michael@0: body: background michael@0: blockquote: cite (not normally rewritable) michael@0: link: href michael@0: frame: src, longdesc michael@0: iframe: src, longdesc michael@0: input: src, usemap michael@0: form: action michael@0: img: src, longdesc, usemap michael@0: script: src michael@0: applet: codebase, archive michael@0: object: codebase, data, classid, usemap michael@0: head: profile michael@0: del: cite michael@0: ins: cite michael@0: q: cite michael@0: */ michael@0: michael@0: /* Here is how to open a channel for testing michael@0: (from embed/qa/testembed/Tests.cpp): michael@0: michael@0: nsCOMPtr theChannel; michael@0: nsCString uri; michael@0: nsCOMPtr theURI; michael@0: rv = NS_NewURI(getter_AddRefs(theURI), theSpec); michael@0: if (!theURI) michael@0: error; michael@0: rv = NS_OpenURI(getter_AddRefs(theChannel), theURI, nullptr, theLoadGroup); michael@0: if (!theChannel) michael@0: error; michael@0: nsCOMPtr theLoadGroup(do_CreateInstance(NS_LOADGROUP_CONTRACTID)); michael@0: if (!theLoadGroup) michael@0: error; michael@0: nsCOMPtr listener(static_cast(qaBrowserImpl)); michael@0: //nsCOMPtr thisListener(do_GetWeakReference(listener)); michael@0: //qaWebBrowser->AddWebBrowserListener(thisListener, NS_GET_IID(nsIStreamListener)); michael@0: michael@0: // this calls nsIStreamListener::OnDataAvailable() michael@0: rv = theChannel->AsyncOpen(listener, nullptr); michael@0: michael@0: nsCOMPtr theRequest = do_QueryInterface(theChannel); michael@0: // Now we can do things on nsIRequest (like what?) michael@0: */ michael@0: michael@0: #include "mozilla/mozalloc.h" michael@0: #include "nsAString.h" michael@0: #include "nsDebug.h" michael@0: #include "nsError.h" michael@0: #include "nsHTMLURIRefObject.h" michael@0: #include "nsID.h" michael@0: #include "nsIDOMAttr.h" michael@0: #include "nsIDOMElement.h" michael@0: #include "nsIDOMMozNamedAttrMap.h" michael@0: #include "nsIDOMNode.h" michael@0: #include "nsISupportsUtils.h" michael@0: #include "nsString.h" michael@0: michael@0: // String classes change too often and I can't keep up. michael@0: // Set this macro to this week's approved case-insensitive compare routine. michael@0: #define MATCHES(tagName, str) tagName.EqualsIgnoreCase(str) michael@0: michael@0: nsHTMLURIRefObject::nsHTMLURIRefObject() michael@0: { michael@0: mCurAttrIndex = mAttributeCnt = 0; michael@0: } michael@0: michael@0: nsHTMLURIRefObject::~nsHTMLURIRefObject() michael@0: { michael@0: } michael@0: michael@0: //Interfaces for addref and release and queryinterface michael@0: NS_IMPL_ISUPPORTS(nsHTMLURIRefObject, nsIURIRefObject) michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLURIRefObject::Reset() michael@0: { michael@0: mCurAttrIndex = 0; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLURIRefObject::GetNextURI(nsAString & aURI) michael@0: { michael@0: NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED); michael@0: michael@0: nsAutoString tagName; michael@0: nsresult rv = mNode->GetNodeName(tagName); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: // Loop over attribute list: michael@0: if (!mAttributes) michael@0: { michael@0: nsCOMPtr element (do_QueryInterface(mNode)); michael@0: NS_ENSURE_TRUE(element, NS_ERROR_INVALID_ARG); michael@0: michael@0: mCurAttrIndex = 0; michael@0: element->GetAttributes(getter_AddRefs(mAttributes)); michael@0: NS_ENSURE_TRUE(mAttributes, NS_ERROR_NOT_INITIALIZED); michael@0: michael@0: rv = mAttributes->GetLength(&mAttributeCnt); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: NS_ENSURE_TRUE(mAttributeCnt, NS_ERROR_FAILURE); michael@0: mCurAttrIndex = 0; michael@0: } michael@0: #ifdef DEBUG_akkana michael@0: printf("Looking at tag '%s'\n", michael@0: NS_LossyConvertUTF16toASCII(tagName).get()); michael@0: #endif michael@0: while (mCurAttrIndex < mAttributeCnt) michael@0: { michael@0: nsCOMPtr attrNode; michael@0: rv = mAttributes->Item(mCurAttrIndex++, getter_AddRefs(attrNode)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: NS_ENSURE_ARG_POINTER(attrNode); michael@0: nsString curAttr; michael@0: rv = attrNode->GetName(curAttr); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: // href >> A, AREA, BASE, LINK michael@0: #ifdef DEBUG_akkana michael@0: printf("Trying to match attribute '%s'\n", michael@0: NS_LossyConvertUTF16toASCII(curAttr).get()); michael@0: #endif michael@0: if (MATCHES(curAttr, "href")) michael@0: { michael@0: if (!MATCHES(tagName, "a") && !MATCHES(tagName, "area") michael@0: && !MATCHES(tagName, "base") && !MATCHES(tagName, "link")) michael@0: continue; michael@0: rv = attrNode->GetValue(aURI); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: nsString uri (aURI); michael@0: // href pointing to a named anchor doesn't count michael@0: if (aURI.First() != char16_t('#')) michael@0: return NS_OK; michael@0: aURI.Truncate(); michael@0: return NS_ERROR_INVALID_ARG; michael@0: } michael@0: // src >> FRAME, IFRAME, IMG, INPUT, SCRIPT michael@0: else if (MATCHES(curAttr, "src")) michael@0: { michael@0: if (!MATCHES(tagName, "img") michael@0: && !MATCHES(tagName, "frame") && !MATCHES(tagName, "iframe") michael@0: && !MATCHES(tagName, "input") && !MATCHES(tagName, "script")) michael@0: continue; michael@0: return attrNode->GetValue(aURI); michael@0: } michael@0: // michael@0: else if (MATCHES(curAttr, "content")) michael@0: { michael@0: if (!MATCHES(tagName, "meta")) michael@0: continue; michael@0: } michael@0: // longdesc >> FRAME, IFRAME, IMG michael@0: else if (MATCHES(curAttr, "longdesc")) michael@0: { michael@0: if (!MATCHES(tagName, "img") michael@0: && !MATCHES(tagName, "frame") && !MATCHES(tagName, "iframe")) michael@0: continue; michael@0: } michael@0: // usemap >> IMG, INPUT, OBJECT michael@0: else if (MATCHES(curAttr, "usemap")) michael@0: { michael@0: if (!MATCHES(tagName, "img") michael@0: && !MATCHES(tagName, "input") && !MATCHES(tagName, "object")) michael@0: continue; michael@0: } michael@0: // action >> FORM michael@0: else if (MATCHES(curAttr, "action")) michael@0: { michael@0: if (!MATCHES(tagName, "form")) michael@0: continue; michael@0: } michael@0: // background >> BODY michael@0: else if (MATCHES(curAttr, "background")) michael@0: { michael@0: if (!MATCHES(tagName, "body")) michael@0: continue; michael@0: } michael@0: // codebase >> OBJECT, APPLET michael@0: else if (MATCHES(curAttr, "codebase")) michael@0: { michael@0: if (!MATCHES(tagName, "meta")) michael@0: continue; michael@0: } michael@0: // classid >> OBJECT michael@0: else if (MATCHES(curAttr, "classid")) michael@0: { michael@0: if (!MATCHES(tagName, "object")) michael@0: continue; michael@0: } michael@0: // data >> OBJECT michael@0: else if (MATCHES(curAttr, "data")) michael@0: { michael@0: if (!MATCHES(tagName, "object")) michael@0: continue; michael@0: } michael@0: // cite >> BLOCKQUOTE, DEL, INS, Q michael@0: else if (MATCHES(curAttr, "cite")) michael@0: { michael@0: if (!MATCHES(tagName, "blockquote") && !MATCHES(tagName, "q") michael@0: && !MATCHES(tagName, "del") && !MATCHES(tagName, "ins")) michael@0: continue; michael@0: } michael@0: // profile >> HEAD michael@0: else if (MATCHES(curAttr, "profile")) michael@0: { michael@0: if (!MATCHES(tagName, "head")) michael@0: continue; michael@0: } michael@0: // archive attribute on APPLET; warning, it contains a list of URIs. michael@0: else if (MATCHES(curAttr, "archive")) michael@0: { michael@0: if (!MATCHES(tagName, "applet")) michael@0: continue; michael@0: } michael@0: } michael@0: // Return a code to indicate that there are no more, michael@0: // to distinguish that case from real errors. michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLURIRefObject::RewriteAllURIs(const nsAString & aOldPat, michael@0: const nsAString & aNewPat, michael@0: bool aMakeRel) michael@0: { michael@0: #ifdef DEBUG_akkana michael@0: printf("Can't rewrite URIs yet\n"); michael@0: #endif michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLURIRefObject::GetNode(nsIDOMNode** aNode) michael@0: { michael@0: NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED); michael@0: NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER); michael@0: *aNode = mNode.get(); michael@0: NS_ADDREF(*aNode); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLURIRefObject::SetNode(nsIDOMNode *aNode) michael@0: { michael@0: mNode = aNode; michael@0: nsAutoString dummyURI; michael@0: if (NS_SUCCEEDED(GetNextURI(dummyURI))) michael@0: { michael@0: mCurAttrIndex = 0; // Reset so we'll get the first node next time michael@0: return NS_OK; michael@0: } michael@0: michael@0: // If there weren't any URIs in the attributes, michael@0: // then don't accept this node. michael@0: mNode = 0; michael@0: return NS_ERROR_INVALID_ARG; michael@0: } michael@0: michael@0: nsresult NS_NewHTMLURIRefObject(nsIURIRefObject** aResult, nsIDOMNode* aNode) michael@0: { michael@0: nsHTMLURIRefObject* refObject = new nsHTMLURIRefObject(); michael@0: nsresult rv = refObject->SetNode(aNode); michael@0: if (NS_FAILED(rv)) { michael@0: *aResult = 0; michael@0: delete refObject; michael@0: return rv; michael@0: } michael@0: return refObject->QueryInterface(NS_GET_IID(nsIURIRefObject), michael@0: (void**)aResult); michael@0: } michael@0: