nsresult ResourceReader::OnWalkURI(const nsACString& aURISpec,
                                   nsContentPolicyType aContentPolicyType) {
  nsresult rv;
  nsCOMPtr<nsIURI> uri;

  rv = NS_NewURI(getter_AddRefs(uri), aURISpec, mParent->GetCharacterSet(),
                 mCurrentBaseURI);
  NS_ENSURE_SUCCESS(rv, rv);
  return OnWalkURI(uri, aContentPolicyType);
}
nsresult ResourceReader::OnWalkAttribute(Element* aElement,
                                         nsContentPolicyType aContentPolicyType,
                                         const char* aAttribute,
                                         const char* aNamespaceURI) {
  nsAutoCString uriSpec;
  ExtractAttribute(aElement, aAttribute, aNamespaceURI, uriSpec);
  if (uriSpec.IsEmpty()) {
    return NS_OK;
  }
  return OnWalkURI(uriSpec, aContentPolicyType);
}
nsresult
ResourceReader::OnWalkAttribute(nsIDOMNode* aNode,
                                const char* aAttribute,
                                const char* aNamespaceURI)
{
    nsAutoCString uriSpec;
    nsresult rv = ExtractAttribute(aNode, aAttribute, aNamespaceURI, uriSpec);
    NS_ENSURE_SUCCESS(rv, rv);
    if (uriSpec.IsEmpty()) {
        return NS_OK;
    }
    return OnWalkURI(uriSpec);
}
nsresult ResourceReader::OnWalkDOMNode(nsINode* aNode) {
  // Fixup xml-stylesheet processing instructions
  if (auto nodeAsPI = dom::ProcessingInstruction::FromNode(aNode)) {
    nsAutoString target;
    nodeAsPI->GetTarget(target);
    if (target.EqualsLiteral("xml-stylesheet")) {
      nsAutoString href;
      GetXMLStyleSheetLink(nodeAsPI, href);
      if (!href.IsEmpty()) {
        return OnWalkURI(NS_ConvertUTF16toUTF8(href),
                         nsIContentPolicy::TYPE_STYLESHEET);
      }
    }
    return NS_OK;
  }

  // Test the node to see if it's an image, frame, iframe, css, js
  if (aNode->IsHTMLElement(nsGkAtoms::img)) {
    return OnWalkAttribute(aNode->AsElement(), nsIContentPolicy::TYPE_IMAGE,
                           "src");
  }

  if (aNode->IsSVGElement(nsGkAtoms::img)) {
    return OnWalkAttribute(aNode->AsElement(), nsIContentPolicy::TYPE_IMAGE,
                           "href", "http://www.w3.org/1999/xlink");
  }

  if (aNode->IsAnyOfHTMLElements(nsGkAtoms::audio, nsGkAtoms::video)) {
    return OnWalkAttribute(aNode->AsElement(), nsIContentPolicy::TYPE_MEDIA,
                           "src");
  }

  if (aNode->IsHTMLElement(nsGkAtoms::source)) {
    return OnWalkAttribute(aNode->AsElement(), nsIContentPolicy::TYPE_MEDIA,
                           "src");
  }

  if (aNode->IsHTMLElement(nsGkAtoms::body)) {
    return OnWalkAttribute(aNode->AsElement(), nsIContentPolicy::TYPE_IMAGE,
                           "background");
  }

  if (aNode->IsHTMLElement(nsGkAtoms::table)) {
    return OnWalkAttribute(aNode->AsElement(), nsIContentPolicy::TYPE_IMAGE,
                           "background");
  }

  if (aNode->IsHTMLElement(nsGkAtoms::tr)) {
    return OnWalkAttribute(aNode->AsElement(), nsIContentPolicy::TYPE_IMAGE,
                           "background");
  }

  if (aNode->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th)) {
    return OnWalkAttribute(aNode->AsElement(), nsIContentPolicy::TYPE_IMAGE,
                           "background");
  }

  if (aNode->IsHTMLElement(nsGkAtoms::script)) {
    return OnWalkAttribute(aNode->AsElement(), nsIContentPolicy::TYPE_SCRIPT,
                           "src");
  }

  if (aNode->IsSVGElement(nsGkAtoms::script)) {
    return OnWalkAttribute(aNode->AsElement(), nsIContentPolicy::TYPE_SCRIPT,
                           "href", "http://www.w3.org/1999/xlink");
  }

  if (aNode->IsHTMLElement(nsGkAtoms::embed)) {
    return OnWalkAttribute(aNode->AsElement(), nsIContentPolicy::TYPE_OBJECT,
                           "src");
  }

  if (aNode->IsHTMLElement(nsGkAtoms::object)) {
    return OnWalkAttribute(aNode->AsElement(), nsIContentPolicy::TYPE_OBJECT,
                           "data");
  }

  if (auto nodeAsLink = dom::HTMLLinkElement::FromNode(aNode)) {
    // Test if the link has a rel value indicating it to be a stylesheet
    nsAutoString linkRel;
    nodeAsLink->GetRel(linkRel);
    if (!linkRel.IsEmpty()) {
      nsReadingIterator<char16_t> start;
      nsReadingIterator<char16_t> end;
      nsReadingIterator<char16_t> current;

      linkRel.BeginReading(start);
      linkRel.EndReading(end);

      // Walk through space delimited string looking for "stylesheet"
      for (current = start; current != end; ++current) {
        // Ignore whitespace
        if (nsCRT::IsAsciiSpace(*current)) {
          continue;
        }

        // Grab the next space delimited word
        nsReadingIterator<char16_t> startWord = current;
        do {
          ++current;
        } while (current != end && !nsCRT::IsAsciiSpace(*current));

        // Store the link for fix up if it says "stylesheet"
        if (Substring(startWord, current)
                .LowerCaseEqualsLiteral("stylesheet")) {
          OnWalkAttribute(aNode->AsElement(), nsIContentPolicy::TYPE_STYLESHEET,
                          "href");
          return NS_OK;
        }
        if (current == end) {
          break;
        }
      }
    }
    return NS_OK;
  }

  if (aNode->IsHTMLElement(nsGkAtoms::frame)) {
    return OnWalkSubframe(aNode);
  }

  if (aNode->IsHTMLElement(nsGkAtoms::iframe) &&
      !(mPersistFlags & IWBP::PERSIST_FLAGS_IGNORE_IFRAMES)) {
    return OnWalkSubframe(aNode);
  }

  auto nodeAsInput = dom::HTMLInputElement::FromNode(aNode);
  if (nodeAsInput) {
    return OnWalkAttribute(aNode->AsElement(), nsIContentPolicy::TYPE_IMAGE,
                           "src");
  }

  return NS_OK;
}
nsresult
ResourceReader::OnWalkDOMNode(nsIDOMNode* aNode)
{
    nsresult rv;

    // Fixup xml-stylesheet processing instructions
    nsCOMPtr<nsIDOMProcessingInstruction> nodeAsPI = do_QueryInterface(aNode);
    if (nodeAsPI) {
        nsAutoString target;
        rv = nodeAsPI->GetTarget(target);
        NS_ENSURE_SUCCESS(rv, rv);
        if (target.EqualsLiteral("xml-stylesheet")) {
            nsAutoString href;
            GetXMLStyleSheetLink(nodeAsPI, href);
            if (!href.IsEmpty()) {
                return OnWalkURI(NS_ConvertUTF16toUTF8(href));
            }
        }
        return NS_OK;
    }

    nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
    if (!content) {
        return NS_OK;
    }

    // Test the node to see if it's an image, frame, iframe, css, js
    nsCOMPtr<nsIDOMHTMLImageElement> nodeAsImage = do_QueryInterface(aNode);
    if (nodeAsImage) {
        return OnWalkAttribute(aNode, "src");
    }

    if (content->IsSVGElement(nsGkAtoms::img)) {
        return OnWalkAttribute(aNode, "href", "http://www.w3.org/1999/xlink");
    }

    nsCOMPtr<nsIDOMHTMLMediaElement> nodeAsMedia = do_QueryInterface(aNode);
    if (nodeAsMedia) {
        return OnWalkAttribute(aNode, "src");
    }
    nsCOMPtr<nsIDOMHTMLSourceElement> nodeAsSource = do_QueryInterface(aNode);
    if (nodeAsSource) {
        return OnWalkAttribute(aNode, "src");
    }

    if (content->IsHTMLElement(nsGkAtoms::body)) {
        return OnWalkAttribute(aNode, "background");
    }

    if (content->IsHTMLElement(nsGkAtoms::table)) {
        return OnWalkAttribute(aNode, "background");
    }

    if (content->IsHTMLElement(nsGkAtoms::tr)) {
        return OnWalkAttribute(aNode, "background");
    }

    if (content->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th)) {
        return OnWalkAttribute(aNode, "background");
    }

    nsCOMPtr<nsIDOMHTMLScriptElement> nodeAsScript = do_QueryInterface(aNode);
    if (nodeAsScript) {
        return OnWalkAttribute(aNode, "src");
    }

    if (content->IsSVGElement(nsGkAtoms::script)) {
        return OnWalkAttribute(aNode, "href", "http://www.w3.org/1999/xlink");
    }

    nsCOMPtr<nsIDOMHTMLEmbedElement> nodeAsEmbed = do_QueryInterface(aNode);
    if (nodeAsEmbed) {
        return OnWalkAttribute(aNode, "src");
    }

    nsCOMPtr<nsIDOMHTMLObjectElement> nodeAsObject = do_QueryInterface(aNode);
    if (nodeAsObject) {
        return OnWalkAttribute(aNode, "data");
    }

    nsCOMPtr<nsIDOMHTMLAppletElement> nodeAsApplet = do_QueryInterface(aNode);
    if (nodeAsApplet) {
        // For an applet, relative URIs are resolved relative to the
        // codebase (which is resolved relative to the base URI).
        nsCOMPtr<nsIURI> oldBase = mCurrentBaseURI;
        nsAutoString codebase;
        rv = nodeAsApplet->GetCodeBase(codebase);
        NS_ENSURE_SUCCESS(rv, rv);
        if (!codebase.IsEmpty()) {
            nsCOMPtr<nsIURI> baseURI;
            rv = NS_NewURI(getter_AddRefs(baseURI), codebase,
                           mParent->GetCharacterSet().get(), mCurrentBaseURI);
            NS_ENSURE_SUCCESS(rv, rv);
            if (baseURI) {
                mCurrentBaseURI = baseURI;
                // Must restore this before returning (or ENSURE'ing).
            }
        }

        // We only store 'code' locally if there is no 'archive',
        // otherwise we assume the archive file(s) contains it (bug 430283).
        nsAutoCString archiveAttr;
        rv = ExtractAttribute(aNode, "archive", "", archiveAttr);
        if (NS_SUCCEEDED(rv)) {
            if (!archiveAttr.IsEmpty()) {
                rv = OnWalkURI(archiveAttr);
            } else {
                rv = OnWalkAttribute(aNode, "core");
            }
        }

        // restore the base URI we really want to have
        mCurrentBaseURI = oldBase;
        return rv;
    }

    nsCOMPtr<nsIDOMHTMLLinkElement> nodeAsLink = do_QueryInterface(aNode);
    if (nodeAsLink) {
        // Test if the link has a rel value indicating it to be a stylesheet
        nsAutoString linkRel;
        if (NS_SUCCEEDED(nodeAsLink->GetRel(linkRel)) && !linkRel.IsEmpty()) {
            nsReadingIterator<char16_t> start;
            nsReadingIterator<char16_t> end;
            nsReadingIterator<char16_t> current;

            linkRel.BeginReading(start);
            linkRel.EndReading(end);

            // Walk through space delimited string looking for "stylesheet"
            for (current = start; current != end; ++current) {
                // Ignore whitespace
                if (nsCRT::IsAsciiSpace(*current)) {
                    continue;
                }

                // Grab the next space delimited word
                nsReadingIterator<char16_t> startWord = current;
                do {
                    ++current;
                } while (current != end && !nsCRT::IsAsciiSpace(*current));

                // Store the link for fix up if it says "stylesheet"
                if (Substring(startWord, current)
                        .LowerCaseEqualsLiteral("stylesheet")) {
                    OnWalkAttribute(aNode, "href");
                    return NS_OK;
                }
                if (current == end) {
                    break;
                }
            }
        }
        return NS_OK;
    }

    nsCOMPtr<nsIDOMHTMLFrameElement> nodeAsFrame = do_QueryInterface(aNode);
    if (nodeAsFrame) {
        return OnWalkSubframe(aNode);
    }

    nsCOMPtr<nsIDOMHTMLIFrameElement> nodeAsIFrame = do_QueryInterface(aNode);
    if (nodeAsIFrame && !(mPersistFlags &
                          IWBP::PERSIST_FLAGS_IGNORE_IFRAMES)) {
        return OnWalkSubframe(aNode);
    }

    nsCOMPtr<nsIDOMHTMLInputElement> nodeAsInput = do_QueryInterface(aNode);
    if (nodeAsInput) {
        return OnWalkAttribute(aNode, "src");
    }

    return NS_OK;
}