Search code examples
firefox-addonxulxpcomidl

Walking through an nsIDOMNodeList


I'm working on a C++ component for Firefox and I'm trying to wrap my mind around XPCOM and all of its parts. It's really confusing so I'm trying to work through it but I'm trying to walk through a page and get all its links. I'm trying to figure out what all the objects do. So if I have this interface:

interface nsIPageSummary : nsISupports {
    boolean saveSummary(in nsIDOMDocument document, 
                        out unsigned long numLinks,
                        out unsigned long numImages);
};

defined in the IDL, the method in my C++ code would look like:

SaveSummary(nsIDOMDocument* inDoc, PRBool* outSuccess)
{
    *outSuccess = PR_FALSE;
    nsCOMPtr<nsIDOMNodeList> nodeList;
    inDoc->GetElementsByTagName(NS_LITERAL_STRING("A"), getter_AddRefs(nodeList));
}

I know the C++ method needs more parameters to match up with the one defined in the interface but I don't understand how all the typing works yet. In terms of the actual list, am I right in understanding that the

inDoc->GetElementsByTagName(NS_LITERAL_STRING("A"), getter_AddRefs(nodeList));

line puts all the "A" tags from the inDoc into the nodeList? And I would just have to walk through nodeList to get them all?


Solution

  • You compile your interface definition using xpidl to get a C++ header file - you can check that file to see how interface definitions are translated. Your method definition should actually look like thit:

    nsresult SaveSummary(nsIDOMDocument* inDoc, PRUint32* outNumLinks, PRUint32* outNumImages, PRBool* outSuccess)
    

    I would suggest to use the type PRUint32 instead of the ambiguous unsigned long in the interface definition as well. I would also suggest getting rid of the return value: XPCOM methods always return nsresult which is either NS_OK or an error code, this is enough to indicate success or failure. An error code is automatically translated into an exception when called from JavaScript. And finally I would recommend using lower-case tag names: while it won't matter in HTML (case-insensitive), in an XHTML document only lower-case tag names are accepted. So your interface definition should look like this:

    interface nsIPageSummary : nsISupports {
        void saveSummary(in nsIDOMDocument document, 
                         out PRUint32 numLinks,
                         out PRUint32 numImages);
    };
    

    And the corresponding implementation:

    nsresult
    SaveSummary(nsIDOMDocument* inDoc, PRUint32* outNumLinks, PRUint32* outNumImages)
    {
      nsresult rv;
    
      nsCOMPtr<nsIDOMNodeList> nodeList;
      rv = inDoc->GetElementsByTagName(NS_LITERAL_STRING("a"), getter_AddRefs(nodeList));
      if (NS_FAILED(rv))
        return rv;
    
      rv = nodeList->GetLength(outNumLinks);
      if (NS_FAILED(rv))
        return rv;
    
      rv = inDoc->GetElementsByTagName(NS_LITERAL_STRING("img"), getter_AddRefs(nodeList));
      if (NS_FAILED(rv))
        return rv;
    
      rv = nodeList->GetLength(outNumImages);
      if (NS_FAILED(rv))
        return rv;
    
      return NS_OK;
    }