Back to index

lightning-sunbird  0.9+nobinonly
nsXMLStylesheetPI.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2002
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Jonas Sicking (original author)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsIDOMLinkStyle.h"
00040 #include "nsIDOMStyleSheet.h"
00041 #include "nsIDocument.h"
00042 #include "nsIStyleSheet.h"
00043 #include "nsIURI.h"
00044 #include "nsStyleLinkElement.h"
00045 #include "nsNetUtil.h"
00046 #include "nsXMLProcessingInstruction.h"
00047 #include "nsUnicharUtils.h"
00048 #include "nsParserUtils.h"
00049 #include "nsHTMLAtoms.h"
00050 
00051 class nsXMLStylesheetPI : public nsXMLProcessingInstruction,
00052                           public nsStyleLinkElement
00053 {
00054 public:
00055   nsXMLStylesheetPI(nsNodeInfoManager *aNodeInfoManager, const nsAString& aData);
00056   virtual ~nsXMLStylesheetPI();
00057 
00058   // nsISupports
00059   NS_DECL_ISUPPORTS_INHERITED
00060 
00061   // nsIDOMNode
00062   NS_IMETHOD SetNodeValue(const nsAString& aData);
00063   NS_IMETHOD CloneNode(PRBool aDeep, nsIDOMNode** aReturn);
00064 
00065   // nsIContent
00066   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
00067                               nsIContent* aBindingParent,
00068                               PRBool aCompileEventHandlers);
00069   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
00070                               PRBool aNullParent = PR_TRUE);
00071   
00072   // nsStyleLinkElement
00073   NS_IMETHOD GetCharset(nsAString& aCharset);
00074 
00075 protected:
00076   void GetStyleSheetURL(PRBool* aIsInline,
00077                         nsIURI** aURI);
00078   void GetStyleSheetInfo(nsAString& aTitle,
00079                          nsAString& aType,
00080                          nsAString& aMedia,
00081                          PRBool* aIsAlternate);
00082 };
00083 
00084 // nsISupports implementation
00085 
00086 NS_INTERFACE_MAP_BEGIN(nsXMLStylesheetPI)
00087   NS_INTERFACE_MAP_ENTRY(nsIDOMLinkStyle)
00088   NS_INTERFACE_MAP_ENTRY(nsIStyleSheetLinkingElement)
00089   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XMLStylesheetProcessingInstruction)
00090 NS_INTERFACE_MAP_END_INHERITING(nsXMLProcessingInstruction)
00091 
00092 NS_IMPL_ADDREF_INHERITED(nsXMLStylesheetPI, nsXMLProcessingInstruction)
00093 NS_IMPL_RELEASE_INHERITED(nsXMLStylesheetPI, nsXMLProcessingInstruction)
00094 
00095 
00096 nsXMLStylesheetPI::nsXMLStylesheetPI(nsNodeInfoManager *aNodeInfoManager,
00097                                      const nsAString& aData)
00098   : nsXMLProcessingInstruction(aNodeInfoManager, NS_LITERAL_STRING("xml-stylesheet"),
00099                                aData)
00100 {
00101 }
00102 
00103 nsXMLStylesheetPI::~nsXMLStylesheetPI()
00104 {
00105 }
00106 
00107 // nsIContent
00108 
00109 nsresult
00110 nsXMLStylesheetPI::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
00111                               nsIContent* aBindingParent,
00112                               PRBool aCompileEventHandlers)
00113 {
00114   nsresult rv = nsXMLProcessingInstruction::BindToTree(aDocument, aParent,
00115                                                        aBindingParent,
00116                                                        aCompileEventHandlers);
00117   NS_ENSURE_SUCCESS(rv, rv);
00118 
00119   UpdateStyleSheet(nsnull);
00120 
00121   return rv;  
00122 }
00123 
00124 void
00125 nsXMLStylesheetPI::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
00126 {
00127   nsCOMPtr<nsIDocument> oldDoc = GetCurrentDoc();
00128 
00129   nsXMLProcessingInstruction::UnbindFromTree(aDeep, aNullParent);
00130   UpdateStyleSheet(oldDoc);
00131 }
00132 
00133 // nsIDOMNode
00134 
00135 NS_IMETHODIMP
00136 nsXMLStylesheetPI::SetNodeValue(const nsAString& aNodeValue)
00137 {
00138   nsresult rv = nsGenericDOMDataNode::SetNodeValue(aNodeValue);
00139   if (NS_SUCCEEDED(rv)) {
00140     UpdateStyleSheet();
00141   }
00142   return rv;
00143 }
00144 
00145 NS_IMETHODIMP
00146 nsXMLStylesheetPI::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
00147 {
00148   nsAutoString data;
00149   GetData(data);
00150 
00151   nsXMLStylesheetPI *pi = new nsXMLStylesheetPI(GetNodeInfoManager(), data);
00152   if (!pi) {
00153     return NS_ERROR_OUT_OF_MEMORY;
00154   }
00155 
00156   NS_ADDREF(*aReturn = pi);
00157 
00158   return NS_OK;
00159 }
00160 
00161 // nsStyleLinkElement
00162 
00163 NS_IMETHODIMP
00164 nsXMLStylesheetPI::GetCharset(nsAString& aCharset)
00165 {
00166   return GetAttrValue(nsHTMLAtoms::charset, aCharset) ? NS_OK : NS_ERROR_FAILURE;
00167 }
00168 
00169 void
00170 nsXMLStylesheetPI::GetStyleSheetURL(PRBool* aIsInline,
00171                                     nsIURI** aURI)
00172 {
00173   *aIsInline = PR_FALSE;
00174   *aURI = nsnull;
00175 
00176   nsAutoString href;
00177   GetAttrValue(nsHTMLAtoms::href, href);
00178   if (href.IsEmpty()) {
00179     return;
00180   }
00181 
00182   nsIURI *baseURL;
00183   nsCAutoString charset;
00184   nsIDocument *document = GetOwnerDoc();
00185   if (document) {
00186     baseURL = document->GetBaseURI();
00187     charset = document->GetDocumentCharacterSet();
00188   } else {
00189     baseURL = nsnull;
00190   }
00191 
00192   NS_NewURI(aURI, href, charset.get(), baseURL);
00193 }
00194 
00195 void
00196 nsXMLStylesheetPI::GetStyleSheetInfo(nsAString& aTitle,
00197                                      nsAString& aType,
00198                                      nsAString& aMedia,
00199                                      PRBool* aIsAlternate)
00200 {
00201   aTitle.Truncate();
00202   aType.Truncate();
00203   aMedia.Truncate();
00204   *aIsAlternate = PR_FALSE;
00205 
00206   // xml-stylesheet PI is special only in prolog
00207   if (!nsContentUtils::InProlog(this)) {
00208     return;
00209   }
00210 
00211   nsAutoString data;
00212   GetData(data);
00213 
00214   nsParserUtils::GetQuotedAttributeValue(data, nsHTMLAtoms::title, aTitle);
00215 
00216   nsAutoString alternate;
00217   nsParserUtils::GetQuotedAttributeValue(data, nsHTMLAtoms::alternate, alternate);
00218 
00219   // if alternate, does it have title?
00220   if (alternate.EqualsLiteral("yes")) {
00221     if (aTitle.IsEmpty()) { // alternates must have title
00222       return;
00223     }
00224 
00225     *aIsAlternate = PR_TRUE;
00226   }
00227 
00228   nsParserUtils::GetQuotedAttributeValue(data, nsHTMLAtoms::media, aMedia);
00229 
00230   nsAutoString type;
00231   nsParserUtils::GetQuotedAttributeValue(data, nsHTMLAtoms::type, type);
00232 
00233   nsAutoString mimeType, notUsed;
00234   nsParserUtils::SplitMimeType(type, mimeType, notUsed);
00235   if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
00236     aType.Assign(type);
00237     return;
00238   }
00239 
00240   // If we get here we assume that we're loading a css file, so set the
00241   // type to 'text/css'
00242   aType.AssignLiteral("text/css");
00243 
00244   return;
00245 }
00246 
00247 nsresult
00248 NS_NewXMLStylesheetProcessingInstruction(nsIContent** aInstancePtrResult,
00249                                          nsNodeInfoManager *aNodeInfoManager,
00250                                          const nsAString& aData)
00251 {
00252   NS_PRECONDITION(aNodeInfoManager, "Missing nodeinfo manager");
00253 
00254   *aInstancePtrResult = nsnull;
00255   
00256   nsXMLStylesheetPI *instance = new nsXMLStylesheetPI(aNodeInfoManager, aData);
00257   if (!instance) {
00258     return NS_ERROR_OUT_OF_MEMORY;
00259   }
00260 
00261   NS_ADDREF(*aInstancePtrResult = instance);
00262 
00263   return NS_OK;
00264 }