diff --git a/mozilla/extensions/transformiix/build/Makefile.in b/mozilla/extensions/transformiix/build/Makefile.in index 5df6f3a6ba2..9882ba405d6 100644 --- a/mozilla/extensions/transformiix/build/Makefile.in +++ b/mozilla/extensions/transformiix/build/Makefile.in @@ -46,6 +46,9 @@ REQUIRES = xpcom \ caps \ locale \ unicharutil \ + htmlparser \ + webshell \ + docshell \ $(NULL) IS_COMPONENT = 1 MODULE_NAME = TransformiixModule diff --git a/mozilla/extensions/transformiix/build/makefile.win b/mozilla/extensions/transformiix/build/makefile.win index 29130cd6d42..3bed33d5182 100644 --- a/mozilla/extensions/transformiix/build/makefile.win +++ b/mozilla/extensions/transformiix/build/makefile.win @@ -30,6 +30,9 @@ REQUIRES = xpcom \ content \ xpconnect \ js \ + htmlparser \ + webshell \ + docshell \ $(NULL) include <$(DEPTH)/config/config.mak> diff --git a/mozilla/extensions/transformiix/source/xslt/Makefile.in b/mozilla/extensions/transformiix/source/xslt/Makefile.in index 5a9028d7529..8dfec90a812 100644 --- a/mozilla/extensions/transformiix/source/xslt/Makefile.in +++ b/mozilla/extensions/transformiix/source/xslt/Makefile.in @@ -41,6 +41,9 @@ REQUIRES = string \ unicharutil \ xpconnect \ js \ + htmlparser \ + webshell \ + docshell \ $(NULL) endif diff --git a/mozilla/extensions/transformiix/source/xslt/makefile.win b/mozilla/extensions/transformiix/source/xslt/makefile.win index aac3953ea5a..a0c9c3b8aaa 100644 --- a/mozilla/extensions/transformiix/source/xslt/makefile.win +++ b/mozilla/extensions/transformiix/source/xslt/makefile.win @@ -31,6 +31,9 @@ REQUIRES = string \ unicharutil \ xpconnect \ js \ + htmlparser \ + webshell \ + docshell \ $(NULL) include <$(DEPTH)/config/config.mak> diff --git a/mozilla/extensions/transformiix/source/xslt/txHTMLAtomList.h b/mozilla/extensions/transformiix/source/xslt/txHTMLAtomList.h index 2f2bc37bd4b..7b9e8048e38 100644 --- a/mozilla/extensions/transformiix/source/xslt/txHTMLAtomList.h +++ b/mozilla/extensions/transformiix/source/xslt/txHTMLAtomList.h @@ -44,6 +44,7 @@ TX_ATOM(button, "button"); TX_ATOM(checked, "checked"); TX_ATOM(col, "col"); TX_ATOM(compact, "compact"); +TX_ATOM(content, "content"); TX_ATOM(declare, "declare"); TX_ATOM(defer, "defer"); TX_ATOM(dir, "dir"); @@ -53,6 +54,8 @@ TX_ATOM(frame, "frame"); TX_ATOM(headerDefaultStyle, "default-style"); TX_ATOM(head, "head"); TX_ATOM(hr, "hr"); +TX_ATOM(href, "href"); +TX_ATOM(httpEquiv, "http-equiv"); TX_ATOM(img, "img"); TX_ATOM(input, "input"); TX_ATOM(isindex, "isindex"); @@ -73,12 +76,14 @@ TX_ATOM(option, "option"); TX_ATOM(p, "p"); TX_ATOM(param, "param"); TX_ATOM(readonly, "readonly"); +TX_ATOM(refresh, "refresh"); TX_ATOM(script, "script"); TX_ATOM(select, "select"); TX_ATOM(selected, "selected"); TX_ATOM(src, "src"); TX_ATOM(style, "style"); TX_ATOM(table, "table"); +TX_ATOM(target, "target"); TX_ATOM(td, "td"); TX_ATOM(textarea, "textarea"); TX_ATOM(th, "th"); diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.cpp b/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.cpp index f7296fbbf4e..46448a44878 100644 --- a/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.cpp @@ -49,6 +49,11 @@ #include "nsIDOMNSDocument.h" #include "nsUnicharUtils.h" #include "txAtoms.h" +#include "nsIParser.h" +#include "nsNetUtil.h" +#include "nsIScriptGlobalObject.h" +#include "nsIRefreshURI.h" +#include "nsIDocShell.h" #define kXHTMLNameSpaceURI "http://www.w3.org/1999/xhtml" #define kTXNameSpaceURI "http://www.mozilla.org/TransforMiix" @@ -128,12 +133,28 @@ void txMozillaXMLOutput::disableStylesheetLoad() void txMozillaXMLOutput::endDocument() { closePrevious(eCloseElement | eFlushText); - if (!mHaveTitle) { + if (!mHaveTitleElement) { nsCOMPtr domDoc = do_QueryInterface(mDocument); if (domDoc) { domDoc->SetTitle(NS_LITERAL_STRING("")); } } + + if (!mRefreshString.IsEmpty()) { + nsCOMPtr doc = do_QueryInterface(mDocument); + nsCOMPtr sgo; + doc->GetScriptGlobalObject(getter_AddRefs(sgo)); + if (sgo) { + nsCOMPtr docShell; + sgo->GetDocShell(getter_AddRefs(docShell)); + nsCOMPtr refURI = do_QueryInterface(docShell); + if (refURI) { + nsCOMPtr baseURI; + doc->GetBaseURL(*getter_AddRefs(baseURI)); + refURI->SetupRefreshURIFromHeader(baseURI, mRefreshString); + } + } + } } void txMozillaXMLOutput::endElement(const String& aName, const PRInt32 aNsID) @@ -147,88 +168,40 @@ void txMozillaXMLOutput::endElement(const String& aName, const PRInt32 aNsID) closePrevious(eCloseElement | eFlushText); - nsresult rv; - - nsCOMPtr currentContent = do_QueryInterface(mCurrentNode, &rv); - NS_ASSERTION(NS_SUCCEEDED(rv), "Can't QI to nsIContent"); - if (!currentContent) - return; - - nsCOMPtr atom; - currentContent->GetTag(*getter_AddRefs(atom)); - - PRBool isHTML = (mOutputFormat.mMethod == eHTMLOutput) && - (aNsID == kNameSpaceID_None); - - if (isHTML && (atom == txHTMLAtoms::table)) { - // Check if we have any table section. - nsCOMPtr section; - nsCOMPtr childContent; - PRInt32 count, i = 0; - - currentContent->ChildCount(count); - while (!section && (i < count)) { - rv = currentContent->ChildAt(i, *getter_AddRefs(childContent)); - NS_ASSERTION(NS_SUCCEEDED(rv), "Something went wrong while getting a child"); - section = do_QueryInterface(childContent); - ++i; - } - - if (!section && (count > 0)) { - // If no section, wrap table's children in a tbody. - nsCOMPtr wrapper; - - rv = mDocument->CreateElementNS(NS_LITERAL_STRING(kXHTMLNameSpaceURI), - NS_LITERAL_STRING("tbody"), - getter_AddRefs(wrapper)); - NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create tbody element"); - - if (wrapper) { - nsCOMPtr resultNode; - - wrapChildren(mCurrentNode, wrapper); - rv = mCurrentNode->AppendChild(wrapper, getter_AddRefs(resultNode)); - NS_ASSERTION(NS_SUCCEEDED(rv), "Can't append tbody element"); - } - } - } - else if (isHTML || (aNsID == kNameSpaceID_HTML)) { - if (mScriptParent && (atom == txHTMLAtoms::script)) { - // Add this script element to the array of loading script elements. - nsCOMPtr scriptElement = do_QueryInterface(mCurrentNode, &rv); - NS_ASSERTION(NS_SUCCEEDED(rv), "Need script element"); - if (!mScriptElements) - rv = NS_NewISupportsArray(getter_AddRefs(mScriptElements)); - NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create array"); - if (NS_SUCCEEDED(rv)) - mScriptElements->AppendElement(scriptElement); - - // Add the script element to the tree. - nsCOMPtr document = do_QueryInterface(mScriptParent); - if (document && !mRootContent) { - mRootContent = do_QueryInterface(mCurrentNode); - mRootContent->SetDocument(document, PR_FALSE, PR_TRUE); - document->SetRootContent(mRootContent); - } - else { - nsCOMPtr resultNode; - rv = mScriptParent->AppendChild(mCurrentNode, - getter_AddRefs(resultNode)); - NS_ASSERTION(NS_SUCCEEDED(rv), "Can't append script element"); - } - mScriptParent = nsnull; - } - else if (mStyleElement && (atom == txHTMLAtoms::style)) { - if (!mDisableStylesheetLoad) { - mStyleElement->SetEnableUpdates(PR_TRUE); - mStyleElement->UpdateStyleSheet(PR_TRUE, nsnull, -1); - } - mStyleElement = nsnull; - } + // Handle html-elements + if ((mOutputFormat.mMethod == eHTMLOutput && aNsID == kNameSpaceID_None) || + aNsID == kNameSpaceID_XHTML) { + nsCOMPtr element = do_QueryInterface(mCurrentNode); + NS_ASSERTION(element, "endElement'ing non-element"); + endHTMLElement(element, aNsID == kNameSpaceID_XHTML); } - nsCOMPtr tempNode = mCurrentNode; - tempNode->GetParentNode(getter_AddRefs(mCurrentNode)); + // Add the element to the tree if it wasn't added before and take one step + // up the tree + // we can't use GetParentNode to check if mCurrentNode is the + // "non-added node" since that does strange things when we've called + // SetDocument manually + if (mCurrentNode == mNonAddedNode) { + nsCOMPtr document = do_QueryInterface(mNonAddedParent); + if (document && !mRootContent) { + mRootContent = do_QueryInterface(mCurrentNode); + mRootContent->SetDocument(document, PR_FALSE, PR_TRUE); + document->SetRootContent(mRootContent); + } + else { + nsCOMPtr resultNode; + mNonAddedParent->AppendChild(mCurrentNode, + getter_AddRefs(resultNode)); + } + mCurrentNode = mNonAddedParent; + mNonAddedParent = nsnull; + mNonAddedNode = nsnull; + } + else { + nsCOMPtr parent; + mCurrentNode->GetParentNode(getter_AddRefs(parent)); + mCurrentNode = parent; + } } nsresult txMozillaXMLOutput::getRootContent(nsIContent** aReturn) @@ -263,10 +236,24 @@ void txMozillaXMLOutput::processingInstruction(const String& aTarget, const Stri getter_AddRefs(pi)); NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create entity reference"); - nsCOMPtr node = do_QueryInterface(pi); + nsCOMPtr ssle = do_QueryInterface(pi); + if (ssle) { + ssle->InitStyleLinkElement(nsnull, PR_FALSE); + ssle->SetEnableUpdates(PR_FALSE); + } + nsCOMPtr resultNode; - mCurrentNode->AppendChild(node, getter_AddRefs(resultNode)); + mCurrentNode->AppendChild(pi, getter_AddRefs(resultNode)); NS_ASSERTION(NS_SUCCEEDED(rv), "Can't append entity reference"); + if (NS_FAILED(rv)) + return; + + if (ssle) { + ssle->SetEnableUpdates(PR_TRUE); + rv = ssle->UpdateStyleSheet(PR_TRUE, nsnull, mStyleSheetCount); + if (NS_SUCCEEDED(rv) || (rv == NS_ERROR_HTMLPARSER_BLOCK)) + mStyleSheetCount++; + } } void txMozillaXMLOutput::removeScriptElement(nsIDOMHTMLScriptElement *aElement) @@ -286,7 +273,12 @@ void txMozillaXMLOutput::setOutputDocument(nsIDOMDocument* aDocument) mDocument = aDocument; mCurrentNode = mDocument; - mHaveTitle = PR_FALSE; + mStyleSheetCount = 0; + mHaveTitleElement = PR_FALSE; + mHaveBaseElement = PR_FALSE; + mNonAddedParent = nsnull; + mNonAddedNode = nsnull; + mRefreshString.Truncate(); nsCOMPtr doc = do_QueryInterface(aDocument); doc->GetNameSpaceManager(*getter_AddRefs(mNameSpaceManager)); @@ -338,6 +330,7 @@ void txMozillaXMLOutput::startElement(const String& aName, } nsCOMPtr element; + mDontAddCurrent = PR_FALSE; if ((mOutputFormat.mMethod == eHTMLOutput) && (aNsID == kNameSpaceID_None)) { // Outputting HTML as XHTML, lowercase element names @@ -377,12 +370,9 @@ void txMozillaXMLOutput::closePrevious(PRInt8 aAction) nsresult rv; PRInt32 namespaceID = kNameSpaceID_None; - nsCOMPtr currentContent = do_QueryInterface(mCurrentNode, &rv); + nsCOMPtr currentContent = do_QueryInterface(mCurrentNode); if (currentContent) currentContent->GetNameSpaceID(namespaceID); - PRBool isHTML = (namespaceID == kNameSpaceID_HTML) || - ((mOutputFormat.mMethod == eHTMLOutput) && - (namespaceID == kNameSpaceID_None)); if ((aAction & eCloseElement) && mParentNode) { nsCOMPtr document = do_QueryInterface(mParentNode); @@ -406,28 +396,11 @@ void txMozillaXMLOutput::closePrevious(PRInt8 aAction) document->SetRootContent(mRootContent); } - PRBool appendNode = PR_TRUE; - if (isHTML) { - nsCOMPtr atom; - currentContent->GetTag(*getter_AddRefs(atom)); - if (atom == txHTMLAtoms::script) { - appendNode = PR_FALSE; - mScriptParent = mParentNode; - } - else if (atom == txHTMLAtoms::style) { - mStyleElement = do_QueryInterface(mCurrentNode); - if (mStyleElement) { - // XXX Trick nsCSSLoader into blocking/notifying us? - // We would need to implement nsIParser and - // pass ourselves as first parameter to - // InitStyleLinkElement. We would then be notified - // of stylesheet loads/load failures. - mStyleElement->InitStyleLinkElement(nsnull, PR_FALSE); - mStyleElement->SetEnableUpdates(PR_FALSE); - } - } + if (mDontAddCurrent && !mNonAddedParent) { + mNonAddedParent = mParentNode; + mNonAddedNode = mCurrentNode; } - if (appendNode) { + else { if (document && !mRootContent) { mRootContent = do_QueryInterface(mCurrentNode); mRootContent->SetDocument(document, PR_FALSE, PR_TRUE); @@ -447,25 +420,10 @@ void txMozillaXMLOutput::closePrevious(PRInt8 aAction) rv = mDocument->CreateTextNode(mText, getter_AddRefs(text)); NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create text node"); - nsCOMPtr node = do_QueryInterface(text); nsCOMPtr resultNode; - mCurrentNode->AppendChild(node, getter_AddRefs(resultNode)); + mCurrentNode->AppendChild(text, getter_AddRefs(resultNode)); NS_ASSERTION(NS_SUCCEEDED(rv), "Can't append text node"); - if (currentContent && !mHaveTitle) { - nsCOMPtr atom; - currentContent->GetTag(*getter_AddRefs(atom)); - if ((atom == txHTMLAtoms::title) && mTitleElement) { - // The first title wins - mHaveTitle = PR_TRUE; - nsCOMPtr domDoc = do_QueryInterface(mDocument); - if (domDoc) { - mText.CompressWhitespace(); - domDoc->SetTitle(mText); - } - mTitleElement = nsnull; - } - } mText.Truncate(); } } @@ -476,11 +434,145 @@ void txMozillaXMLOutput::startHTMLElement(nsIDOMElement* aElement) nsCOMPtr content = do_QueryInterface(aElement); content->GetTag(*getter_AddRefs(atom)); - if ((atom == txHTMLAtoms::title) && !mHaveTitle) { - mTitleElement = aElement; + mDontAddCurrent = (atom == txHTMLAtoms::script); + + nsCOMPtr ssle = + do_QueryInterface(aElement); + if (ssle) { + // XXX Trick nsCSSLoader into blocking/notifying us? + // We would need to implement nsIParser and + // pass ourselves as first parameter to + // InitStyleLinkElement. We would then be notified + // of stylesheet loads/load failures. + ssle->InitStyleLinkElement(nsnull, PR_FALSE); + ssle->SetEnableUpdates(PR_FALSE); } } +void txMozillaXMLOutput::endHTMLElement(nsIDOMElement* aElement, + PRBool aXHTML) +{ + nsresult rv; + nsCOMPtr content = do_QueryInterface(aElement); + NS_ASSERTION(content, "Can't QI to nsIContent"); + + nsCOMPtr atom; + content->GetTag(*getter_AddRefs(atom)); + + // add to tables if there is none (not in xhtml) + if (atom == txHTMLAtoms::table && !aXHTML) { + // Check if we have any table section. + nsCOMPtr section; + nsCOMPtr childContent; + PRInt32 count, i = 0; + + content->ChildCount(count); + while (!section && (i < count)) { + rv = content->ChildAt(i, *getter_AddRefs(childContent)); + NS_ASSERTION(NS_SUCCEEDED(rv), "Something went wrong while getting a child"); + section = do_QueryInterface(childContent); + ++i; + } + + if (!section && (count > 0)) { + // If no section, wrap table's children in a tbody. + nsCOMPtr wrapper; + + rv = mDocument->CreateElementNS(NS_LITERAL_STRING(kXHTMLNameSpaceURI), + NS_LITERAL_STRING("tbody"), + getter_AddRefs(wrapper)); + NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create tbody element"); + + if (wrapper) { + nsCOMPtr resultNode; + + wrapChildren(mCurrentNode, wrapper); + rv = mCurrentNode->AppendChild(wrapper, getter_AddRefs(resultNode)); + NS_ASSERTION(NS_SUCCEEDED(rv), "Can't append tbody element"); + } + } + } + // Load scripts + else if (atom == txHTMLAtoms::script) { + // Add this script element to the array of loading script elements. + nsCOMPtr scriptElement = + do_QueryInterface(mCurrentNode); + NS_ASSERTION(scriptElement, "Need script element"); + if (!mScriptElements) + NS_NewISupportsArray(getter_AddRefs(mScriptElements)); + NS_ASSERTION(mScriptElements, "Can't create array"); + if (mScriptElements) + mScriptElements->AppendElement(scriptElement); + } + // Set document title + else if (atom == txHTMLAtoms::title && !mHaveTitleElement) { + // The first title wins + mHaveTitleElement = PR_TRUE; + nsCOMPtr domDoc = do_QueryInterface(mDocument); + nsCOMPtr textNode; + aElement->GetFirstChild(getter_AddRefs(textNode)); + if (domDoc && textNode) { + nsAutoString text; + textNode->GetNodeValue(text); + text.CompressWhitespace(); + domDoc->SetTitle(text); + } + } + else if (atom == txHTMLAtoms::base && !mHaveBaseElement) { + // The first base wins + mHaveBaseElement = PR_TRUE; + + nsCOMPtr doc = do_QueryInterface(mDocument); + NS_ASSERTION(doc, "document doesn't implement nsIDocument"); + nsAutoString value; + content->GetAttr(kNameSpaceID_None, txHTMLAtoms::target, value); + doc->SetBaseTarget(value); + + content->GetAttr(kNameSpaceID_None, txHTMLAtoms::href, value); + nsCOMPtr baseURI; + rv = NS_NewURI(getter_AddRefs(baseURI), value, nsnull); + if (NS_FAILED(rv)) + return; + doc->SetBaseURL(baseURI); // The document checks if it is legal to set this base + } + else if (atom == txHTMLAtoms::meta) { + // handle HTTP-EQUIV data + nsAutoString httpEquiv; + content->GetAttr(kNameSpaceID_None, txHTMLAtoms::httpEquiv, httpEquiv); + if (httpEquiv.IsEmpty()) + return; + + nsAutoString value; + content->GetAttr(kNameSpaceID_None, txHTMLAtoms::content, value); + if (value.IsEmpty()) + return; + + ToLowerCase(httpEquiv); + nsCOMPtr header = dont_AddRef(NS_NewAtom(httpEquiv)); + processHTTPEquiv(header, value); + } + + // Handle all sorts of stylesheets + if (!mDisableStylesheetLoad) { + nsCOMPtr ssle = + do_QueryInterface(aElement); + if (ssle) { + ssle->SetEnableUpdates(PR_TRUE); + rv = ssle->UpdateStyleSheet(PR_TRUE, nsnull, mStyleSheetCount); + if (NS_SUCCEEDED(rv) || (rv == NS_ERROR_HTMLPARSER_BLOCK)) + mStyleSheetCount++; + } + } +} + +void txMozillaXMLOutput::processHTTPEquiv(nsIAtom* aHeader, nsAReadableString& aValue) +{ + // For now we only handle "refresh". There's a longer list in + // HTMLContentSink::ProcessHeaderData + if (aHeader == txHTMLAtoms::refresh) + mRefreshString.Assign(aValue); +} + void txMozillaXMLOutput::wrapChildren(nsIDOMNode* aCurrentNode, nsIDOMElement* aWrapper) { diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.h b/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.h index 2719c4e3cd5..896cd40b5df 100644 --- a/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.h +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaXMLOutput.h @@ -161,6 +161,8 @@ public: private: void closePrevious(PRInt8 aAction); void startHTMLElement(nsIDOMElement* aElement); + void endHTMLElement(nsIDOMElement* aElement, PRBool aXHTML); + void processHTTPEquiv(nsIAtom* aHeader, nsAReadableString& aValue); void wrapChildren(nsIDOMNode* aCurrentNode, nsIDOMElement* aWrapper); nsCOMPtr mDocument; @@ -168,9 +170,11 @@ private: nsCOMPtr mParentNode; nsCOMPtr mRootContent; - nsCOMPtr mScriptParent; - nsCOMPtr mTitleElement; - nsCOMPtr mStyleElement; + nsCOMPtr mNonAddedParent; + nsCOMPtr mNonAddedNode; + + PRInt32 mStyleSheetCount; + nsAutoString mRefreshString; nsCOMPtr mNameSpaceManager; @@ -180,8 +184,11 @@ private: txOutputFormat mOutputFormat; - PRPackedBool mHaveTitle; PRPackedBool mDisableStylesheetLoad; + PRPackedBool mDontAddCurrent; + + PRPackedBool mHaveTitleElement; + PRPackedBool mHaveBaseElement; enum txAction { eCloseElement = 1, eFlushText = 2 }; };