Bug 1179967 - Always rewrite links to absolute in nsWebBrowserPersist instead of side-effecting document. r=jst
authorJed Davis <jld@mozilla.com>
Wed, 15 Jul 2015 12:15:48 -0700
changeset 253044 77f5030f0742c07e7793cc2941a20ba1935bdb70
parent 253043 142992f32215ac24c4135dfd89ae4ac2759c8915
child 253045 245bf6f333722e96e3ec72ec03491503a8294ea8
push id14039
push usermozilla@noorenberghe.ca
push dateWed, 15 Jul 2015 19:20:10 +0000
treeherderfx-team@245bf6f33372 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjst
bugs1179967
milestone42.0a1
Bug 1179967 - Always rewrite links to absolute in nsWebBrowserPersist instead of side-effecting document. r=jst
embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp
embedding/components/webbrowserpersist/nsWebBrowserPersist.h
--- a/embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -1669,32 +1669,28 @@ nsresult nsWebBrowserPersist::SaveDocume
 
         mCurrentThingsToPersist = oldThingsToPersist;
         mCurrentDataPath = oldDataPath;
         mCurrentDataPathIsRelative = oldDataPathIsRelative;
         mCurrentRelativePathToData = oldCurrentRelativePathToData;
     }
     else
     {
-        // Set the document base to ensure relative links still work
-        SetDocumentBase(aDocument, mCurrentBaseURI);
-
         // Get the content type to save with
         nsXPIDLString realContentType;
         GetDocEncoderContentType(aDocument,
             !mContentType.IsEmpty() ? mContentType.get() : nullptr,
             getter_Copies(realContentType));
 
         nsAutoCString contentType; contentType.AssignWithConversion(realContentType);
         nsAutoCString charType; // Empty
 
         // Save the document
         rv = SaveDocumentWithFixup(
             aDocument,
-            nullptr,  // no dom fixup
             aFile,
             mReplaceExisting,
             contentType,
             charType,
             mEncodingFlags);
         NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
     }
 
@@ -1723,34 +1719,28 @@ nsresult nsWebBrowserPersist::SaveDocume
             break;
         }
 
         mCurrentBaseURI = docData->mBaseURI;
         mCurrentCharset = docData->mCharset;
 
         // Save the document, fixing it up with the new URIs as we do
 
-        nsEncoderNodeFixup *nodeFixup;
-        nodeFixup = new nsEncoderNodeFixup;
-        if (nodeFixup)
-            nodeFixup->mWebBrowserPersist = this;
-
         // Get the content type
         nsXPIDLString realContentType;
         GetDocEncoderContentType(docData->mDocument,
             !mContentType.IsEmpty() ? mContentType.get() : nullptr,
             getter_Copies(realContentType));
 
         nsAutoCString contentType; contentType.AssignWithConversion(realContentType.get());
         nsAutoCString charType; // Empty
 
         // Save the document, fixing up the links as it goes out
         rv = SaveDocumentWithFixup(
             docData->mDocument,
-            nodeFixup,
             docData->mFile,
             mReplaceExisting,
             contentType,
             charType,
             mEncodingFlags);
 
         if (NS_FAILED(rv))
             break;
@@ -3669,22 +3659,25 @@ nsWebBrowserPersist::CreateChannelFromUR
 
     rv = (*aChannel)->SetNotificationCallbacks(static_cast<nsIInterfaceRequestor*>(this));
     NS_ENSURE_SUCCESS(rv, rv);
     return NS_OK;
 }
 
 nsresult
 nsWebBrowserPersist::SaveDocumentWithFixup(
-    nsIDOMDocument *aDocument, nsIDocumentEncoderNodeFixup *aNodeFixup,
+    nsIDOMDocument *aDocument,
     nsIURI *aFile, bool aReplaceExisting, const nsACString &aFormatType,
     const nsCString &aSaveCharset, uint32_t aFlags)
 {
     NS_ENSURE_ARG_POINTER(aFile);
 
+    nsRefPtr<nsEncoderNodeFixup> nodeFixup = new nsEncoderNodeFixup();
+    nodeFixup->mWebBrowserPersist = this;
+
     nsresult  rv = NS_OK;
     nsCOMPtr<nsIFile> localFile;
     GetLocalFileFromURI(aFile, getter_AddRefs(localFile));
     if (localFile)
     {
         // if we're not replacing an existing file but the file
         // exists, something is wrong
         bool fileExists = false;
@@ -3713,17 +3706,17 @@ nsWebBrowserPersist::SaveDocumentWithFix
 
     NS_ConvertASCIItoUTF16 newContentType(aFormatType);
     rv = encoder->Init(aDocument, newContentType, aFlags);
     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
     mTargetBaseURI = aFile;
 
     // Set the node fixup callback
-    encoder->SetNodeFixup(aNodeFixup);
+    encoder->SetNodeFixup(nodeFixup);
 
     if (mWrapColumn && (aFlags & ENCODE_FLAGS_WRAP))
         encoder->SetWrapColumn(mWrapColumn);
 
     nsAutoCString charsetStr(aSaveCharset);
     if (charsetStr.IsEmpty())
     {
         nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDocument);
@@ -3805,233 +3798,16 @@ nsWebBrowserPersist::MakeAndStoreLocalFi
     if (aData)
     {
         *aData = data;
     }
 
     return NS_OK;
 }
 
-// Ordered so that typical documents work fastest.
-//                                    strlen("blockquote")==10
-static const char kSpecialXHTMLTags[][11] = {
-    "body",
-    "head",
-    "img",
-    "script",
-    "a",
-    "area",
-    "link",
-    "input",
-    "frame",
-    "iframe",
-    "object",
-    "applet",
-    "form",
-    "blockquote",
-    "q",
-    "del",
-    "ins"
-};
-
-static bool IsSpecialXHTMLTag(nsIDOMNode *aNode)
-{
-    nsAutoString tmp;
-    aNode->GetNamespaceURI(tmp);
-    if (!tmp.EqualsLiteral("http://www.w3.org/1999/xhtml"))
-        return false;
-
-    aNode->GetLocalName(tmp);
-    for (uint32_t i = 0; i < ArrayLength(kSpecialXHTMLTags); i++) {
-        if (tmp.EqualsASCII(kSpecialXHTMLTags[i]))
-        {
-            // XXX This element MAY have URI attributes, but
-            //     we are not actually checking if they are present.
-            //     That would slow us down further, and I am not so sure
-            //     how important that would be.
-            return true;
-        }
-    }
-
-    return false;
-}
-
-static bool HasSpecialXHTMLTags(nsIDOMNode *aParent)
-{
-    if (IsSpecialXHTMLTag(aParent))
-        return true;
-
-    nsCOMPtr<nsIDOMNodeList> list;
-    aParent->GetChildNodes(getter_AddRefs(list));
-    if (list)
-    {
-        uint32_t count;
-        list->GetLength(&count);
-        uint32_t i;
-        for (i = 0; i < count; i++) {
-            nsCOMPtr<nsIDOMNode> node;
-            list->Item(i, getter_AddRefs(node));
-            if (!node)
-                break;
-            uint16_t nodeType;
-            node->GetNodeType(&nodeType);
-            if (nodeType == nsIDOMNode::ELEMENT_NODE) {
-                return HasSpecialXHTMLTags(node);
-            }
-        }
-    }
-
-    return false;
-}
-
-static bool NeedXHTMLBaseTag(nsIDOMDocument *aDocument)
-{
-    nsCOMPtr<nsIDOMElement> docElement;
-    aDocument->GetDocumentElement(getter_AddRefs(docElement));
-
-    nsCOMPtr<nsIDOMNode> node(do_QueryInterface(docElement));
-    if (node)
-    {
-        return HasSpecialXHTMLTags(node);
-    }
-
-    return false;
-}
-
-// Set document base. This could create an invalid XML document (still well-formed).
-nsresult
-nsWebBrowserPersist::SetDocumentBase(
-    nsIDOMDocument *aDocument, nsIURI *aBaseURI)
-{
-    if (mPersistFlags & PERSIST_FLAGS_NO_BASE_TAG_MODIFICATIONS)
-    {
-        return NS_OK;
-    }
-
-    NS_ENSURE_ARG_POINTER(aBaseURI);
-
-    nsCOMPtr<nsIDOMXMLDocument> xmlDoc;
-    nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(aDocument);
-    if (!htmlDoc)
-    {
-        xmlDoc = do_QueryInterface(aDocument);
-        if (!xmlDoc)
-        {
-            return NS_ERROR_FAILURE;
-        }
-    }
-
-    NS_NAMED_LITERAL_STRING(kXHTMLNS, "http://www.w3.org/1999/xhtml");
-    NS_NAMED_LITERAL_STRING(kHead, "head");
-
-    // Find the head element
-    nsCOMPtr<nsIDOMElement> headElement;
-    nsCOMPtr<nsIDOMNodeList> headList;
-    if (xmlDoc)
-    {
-        // First see if there is XHTML content that needs base
-        // tags.
-        if (!NeedXHTMLBaseTag(aDocument))
-            return NS_OK;
-
-        aDocument->GetElementsByTagNameNS(
-            kXHTMLNS,
-            kHead, getter_AddRefs(headList));
-    }
-    else
-    {
-        aDocument->GetElementsByTagName(
-            kHead, getter_AddRefs(headList));
-    }
-    if (headList)
-    {
-        nsCOMPtr<nsIDOMNode> headNode;
-        headList->Item(0, getter_AddRefs(headNode));
-        headElement = do_QueryInterface(headNode);
-    }
-    if (!headElement)
-    {
-        // Create head and insert as first element
-        nsCOMPtr<nsIDOMNode> firstChildNode;
-        nsCOMPtr<nsIDOMNode> newNode;
-        if (xmlDoc)
-        {
-            aDocument->CreateElementNS(
-                kXHTMLNS,
-                kHead, getter_AddRefs(headElement));
-        }
-        else
-        {
-            aDocument->CreateElement(
-                kHead, getter_AddRefs(headElement));
-        }
-        nsCOMPtr<nsIDOMElement> documentElement;
-        aDocument->GetDocumentElement(getter_AddRefs(documentElement));
-        if (documentElement)
-        {
-            documentElement->GetFirstChild(getter_AddRefs(firstChildNode));
-            documentElement->InsertBefore(headElement, firstChildNode, getter_AddRefs(newNode));
-        }
-    }
-    if (!headElement)
-    {
-        return NS_ERROR_FAILURE;
-    }
-
-    // Find or create the BASE element
-    NS_NAMED_LITERAL_STRING(kBase, "base");
-    nsCOMPtr<nsIDOMElement> baseElement;
-    nsCOMPtr<nsIDOMHTMLCollection> baseList;
-    if (xmlDoc)
-    {
-        headElement->GetElementsByTagNameNS(
-            kXHTMLNS,
-            kBase, getter_AddRefs(baseList));
-    }
-    else
-    {
-        headElement->GetElementsByTagName(
-            kBase, getter_AddRefs(baseList));
-    }
-    if (baseList)
-    {
-        nsCOMPtr<nsIDOMNode> baseNode;
-        baseList->Item(0, getter_AddRefs(baseNode));
-        baseElement = do_QueryInterface(baseNode);
-    }
-
-    // Add the BASE element
-    if (!baseElement)
-    {
-      nsCOMPtr<nsIDOMNode> newNode;
-      if (xmlDoc)
-      {
-          aDocument->CreateElementNS(
-              kXHTMLNS,
-              kBase, getter_AddRefs(baseElement));
-      }
-      else
-      {
-          aDocument->CreateElement(
-              kBase, getter_AddRefs(baseElement));
-      }
-      headElement->AppendChild(baseElement, getter_AddRefs(newNode));
-    }
-    if (!baseElement)
-    {
-        return NS_ERROR_FAILURE;
-    }
-    nsAutoCString uriSpec;
-    aBaseURI->GetSpec(uriSpec);
-    NS_ConvertUTF8toUTF16 href(uriSpec);
-    baseElement->SetAttribute(NS_LITERAL_STRING("href"), href);
-
-    return NS_OK;
-}
-
 // Decide if we need to apply conversion to the passed channel.
 void nsWebBrowserPersist::SetApplyConversionIfNeeded(nsIChannel *aChannel)
 {
     nsresult rv = NS_OK;
     nsCOMPtr<nsIEncodedChannel> encChannel = do_QueryInterface(aChannel, &rv);
     if (NS_FAILED(rv))
         return;
 
--- a/embedding/components/webbrowserpersist/nsWebBrowserPersist.h
+++ b/embedding/components/webbrowserpersist/nsWebBrowserPersist.h
@@ -133,22 +133,21 @@ private:
         return FixupNodeAttributeNS(aNode, "", aAttribute);
     }
     nsresult FixupAnchor(nsIDOMNode *aNode);
     nsresult FixupXMLStyleSheetLink(nsIDOMProcessingInstruction *aPI, const nsAString &aHref);
     nsresult GetXMLStyleSheetLink(nsIDOMProcessingInstruction *aPI, nsAString &aHref);
 
     nsresult StoreAndFixupStyleSheet(nsIStyleSheet *aStyleSheet);
     nsresult SaveDocumentWithFixup(
-        nsIDOMDocument *pDocument, nsIDocumentEncoderNodeFixup *pFixup,
+        nsIDOMDocument *pDocument,
         nsIURI *aFile, bool aReplaceExisting, const nsACString &aFormatType,
         const nsCString &aSaveCharset, uint32_t  aFlags);
     nsresult SaveSubframeContent(
         nsIDOMDocument *aFrameContent, URIData *aData);
-    nsresult SetDocumentBase(nsIDOMDocument *aDocument, nsIURI *aBaseURI);
     nsresult SendErrorStatusChange(
         bool aIsReadError, nsresult aResult, nsIRequest *aRequest, nsIURI *aURI);
     nsresult OnWalkDOMNode(nsIDOMNode *aNode);
 
     nsresult FixRedirectedChannelEntry(nsIChannel *aNewChannel);
 
     void EndDownload(nsresult aResult = NS_OK);
     nsresult SaveGatheredURIs(nsIURI *aFileAsURI);