LCOV - code coverage report
Current view: directory - content/base/src - nsStyleLinkElement.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 133 34 25.6 %
Date: 2012-06-02 Functions: 16 8 50.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2                 :  *
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla Communicator client code, released
      17                 :  * March 31, 1998.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * Netscape Communications Corporation.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 1998-1999
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : /*
      41                 :  * A base class which implements nsIStyleSheetLinkingElement and can
      42                 :  * be subclassed by various content nodes that want to load
      43                 :  * stylesheets (<style>, <link>, processing instructions, etc).
      44                 :  */
      45                 : 
      46                 : #include "nsStyleLinkElement.h"
      47                 : 
      48                 : #include "nsIContent.h"
      49                 : #include "mozilla/css/Loader.h"
      50                 : #include "nsCSSStyleSheet.h"
      51                 : #include "nsIDocument.h"
      52                 : #include "nsIDOMComment.h"
      53                 : #include "nsIDOMNode.h"
      54                 : #include "nsIDOMStyleSheet.h"
      55                 : #include "nsNetUtil.h"
      56                 : #include "nsUnicharUtils.h"
      57                 : #include "nsCRT.h"
      58                 : #include "nsXPCOMCIDInternal.h"
      59                 : #include "nsUnicharInputStream.h"
      60                 : #include "nsContentUtils.h"
      61                 : 
      62              62 : nsStyleLinkElement::nsStyleLinkElement()
      63                 :   : mDontLoadStyle(false)
      64                 :   , mUpdatesEnabled(true)
      65              62 :   , mLineNumber(1)
      66                 : {
      67              62 : }
      68                 : 
      69             124 : nsStyleLinkElement::~nsStyleLinkElement()
      70                 : {
      71              62 :   nsStyleLinkElement::SetStyleSheet(nsnull);
      72             124 : }
      73                 : 
      74                 : NS_IMETHODIMP 
      75              62 : nsStyleLinkElement::SetStyleSheet(nsIStyleSheet* aStyleSheet)
      76                 : {
      77             124 :   nsRefPtr<nsCSSStyleSheet> cssSheet = do_QueryObject(mStyleSheet);
      78              62 :   if (cssSheet) {
      79               0 :     cssSheet->SetOwningNode(nsnull);
      80                 :   }
      81                 : 
      82              62 :   mStyleSheet = aStyleSheet;
      83              62 :   cssSheet = do_QueryObject(mStyleSheet);
      84              62 :   if (cssSheet) {
      85               0 :     nsCOMPtr<nsIDOMNode> node;
      86                 :     CallQueryInterface(this,
      87               0 :                        static_cast<nsIDOMNode**>(getter_AddRefs(node)));
      88               0 :     if (node) {
      89               0 :       cssSheet->SetOwningNode(node);
      90                 :     }
      91                 :   }
      92                 :     
      93              62 :   return NS_OK;
      94                 : }
      95                 : 
      96                 : NS_IMETHODIMP 
      97               0 : nsStyleLinkElement::GetStyleSheet(nsIStyleSheet*& aStyleSheet)
      98                 : {
      99               0 :   aStyleSheet = mStyleSheet;
     100               0 :   NS_IF_ADDREF(aStyleSheet);
     101                 : 
     102               0 :   return NS_OK;
     103                 : }
     104                 : 
     105                 : NS_IMETHODIMP 
     106              62 : nsStyleLinkElement::InitStyleLinkElement(bool aDontLoadStyle)
     107                 : {
     108              62 :   mDontLoadStyle = aDontLoadStyle;
     109                 : 
     110              62 :   return NS_OK;
     111                 : }
     112                 : 
     113                 : NS_IMETHODIMP
     114               0 : nsStyleLinkElement::GetSheet(nsIDOMStyleSheet** aSheet)
     115                 : {
     116               0 :   NS_ENSURE_ARG_POINTER(aSheet);
     117               0 :   *aSheet = nsnull;
     118                 : 
     119               0 :   if (mStyleSheet) {
     120               0 :     CallQueryInterface(mStyleSheet, aSheet);
     121                 :   }
     122                 : 
     123                 :   // Always return NS_OK to avoid throwing JS exceptions if mStyleSheet 
     124                 :   // is not a nsIDOMStyleSheet
     125               0 :   return NS_OK;
     126                 : }
     127                 : 
     128                 : NS_IMETHODIMP
     129             124 : nsStyleLinkElement::SetEnableUpdates(bool aEnableUpdates)
     130                 : {
     131             124 :   mUpdatesEnabled = aEnableUpdates;
     132                 : 
     133             124 :   return NS_OK;
     134                 : }
     135                 : 
     136                 : NS_IMETHODIMP
     137               0 : nsStyleLinkElement::GetCharset(nsAString& aCharset)
     138                 : {
     139                 :   // descendants have to implement this themselves
     140               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     141                 : }
     142                 : 
     143                 : /* virtual */ void
     144               0 : nsStyleLinkElement::OverrideBaseURI(nsIURI* aNewBaseURI)
     145                 : {
     146                 :   NS_NOTREACHED("Base URI can't be overriden in this implementation "
     147               0 :                 "of nsIStyleSheetLinkingElement.");
     148               0 : }
     149                 : 
     150                 : /* virtual */ void
     151               0 : nsStyleLinkElement::SetLineNumber(PRUint32 aLineNumber)
     152                 : {
     153               0 :   mLineNumber = aLineNumber;
     154               0 : }
     155                 : 
     156               0 : PRUint32 ToLinkMask(const nsAString& aLink)
     157                 : { 
     158               0 :   if (aLink.EqualsLiteral("prefetch"))
     159               0 :      return PREFETCH;
     160               0 :   else if (aLink.EqualsLiteral("dns-prefetch"))
     161               0 :      return DNS_PREFETCH;
     162               0 :   else if (aLink.EqualsLiteral("stylesheet"))
     163               0 :     return STYLESHEET;
     164               0 :   else if (aLink.EqualsLiteral("next"))
     165               0 :     return NEXT;
     166               0 :   else if (aLink.EqualsLiteral("alternate"))
     167               0 :     return ALTERNATE;
     168                 :   else 
     169               0 :     return 0;
     170                 : }
     171                 : 
     172               0 : PRUint32 nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes)
     173                 : {
     174               0 :   PRUint32 linkMask = 0;
     175               0 :   nsAString::const_iterator start, done;
     176               0 :   aTypes.BeginReading(start);
     177               0 :   aTypes.EndReading(done);
     178               0 :   if (start == done)
     179               0 :     return linkMask;
     180                 : 
     181               0 :   nsAString::const_iterator current(start);
     182               0 :   bool inString = !nsContentUtils::IsHTMLWhitespace(*current);
     183               0 :   nsAutoString subString;
     184                 :   
     185               0 :   while (current != done) {
     186               0 :     if (nsContentUtils::IsHTMLWhitespace(*current)) {
     187               0 :       if (inString) {
     188               0 :         nsContentUtils::ASCIIToLower(Substring(start, current), subString);
     189               0 :         linkMask |= ToLinkMask(subString);
     190               0 :         inString = false;
     191                 :       }
     192                 :     }
     193                 :     else {
     194               0 :       if (!inString) {
     195               0 :         start = current;
     196               0 :         inString = true;
     197                 :       }
     198                 :     }
     199               0 :     ++current;
     200                 :   }
     201               0 :   if (inString) {
     202               0 :     nsContentUtils::ASCIIToLower(Substring(start, current), subString);
     203               0 :     linkMask |= ToLinkMask(subString);
     204                 :   }
     205               0 :   return linkMask;
     206                 : }
     207                 : 
     208                 : NS_IMETHODIMP
     209              62 : nsStyleLinkElement::UpdateStyleSheet(nsICSSLoaderObserver* aObserver,
     210                 :                                      bool* aWillNotify,
     211                 :                                      bool* aIsAlternate)
     212                 : {
     213                 :   return DoUpdateStyleSheet(nsnull, aObserver, aWillNotify, aIsAlternate,
     214              62 :                             false);
     215                 : }
     216                 : 
     217                 : nsresult
     218             124 : nsStyleLinkElement::UpdateStyleSheetInternal(nsIDocument *aOldDocument,
     219                 :                                              bool aForceUpdate)
     220                 : {
     221                 :   bool notify, alternate;
     222                 :   return DoUpdateStyleSheet(aOldDocument, nsnull, &notify, &alternate,
     223             124 :                             aForceUpdate);
     224                 : }
     225                 : 
     226                 : nsresult
     227             186 : nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument *aOldDocument,
     228                 :                                        nsICSSLoaderObserver* aObserver,
     229                 :                                        bool* aWillNotify,
     230                 :                                        bool* aIsAlternate,
     231                 :                                        bool aForceUpdate)
     232                 : {
     233             186 :   *aWillNotify = false;
     234                 : 
     235             186 :   if (mStyleSheet && aOldDocument) {
     236                 :     // We're removing the link element from the document, unload the
     237                 :     // stylesheet.  We want to do this even if updates are disabled, since
     238                 :     // otherwise a sheet with a stale linking element pointer will be hanging
     239                 :     // around -- not good!
     240               0 :     aOldDocument->BeginUpdate(UPDATE_STYLE);
     241               0 :     aOldDocument->RemoveStyleSheet(mStyleSheet);
     242               0 :     aOldDocument->EndUpdate(UPDATE_STYLE);
     243               0 :     nsStyleLinkElement::SetStyleSheet(nsnull);
     244                 :   }
     245                 : 
     246             186 :   if (mDontLoadStyle || !mUpdatesEnabled) {
     247              62 :     return NS_OK;
     248                 :   }
     249                 : 
     250             248 :   nsCOMPtr<nsIContent> thisContent;
     251             124 :   QueryInterface(NS_GET_IID(nsIContent), getter_AddRefs(thisContent));
     252                 : 
     253             124 :   NS_ENSURE_TRUE(thisContent, NS_ERROR_FAILURE);
     254                 : 
     255             248 :   nsCOMPtr<nsIDocument> doc = thisContent->GetDocument();
     256                 : 
     257             124 :   if (!doc || !doc->CSSLoader()->GetEnabled()) {
     258             124 :     return NS_OK;
     259                 :   }
     260                 : 
     261                 :   bool isInline;
     262               0 :   nsCOMPtr<nsIURI> uri = GetStyleSheetURL(&isInline);
     263                 : 
     264               0 :   if (!aForceUpdate && mStyleSheet && !isInline && uri) {
     265               0 :     nsIURI* oldURI = mStyleSheet->GetSheetURI();
     266               0 :     if (oldURI) {
     267                 :       bool equal;
     268               0 :       nsresult rv = oldURI->Equals(uri, &equal);
     269               0 :       if (NS_SUCCEEDED(rv) && equal) {
     270               0 :         return NS_OK; // We already loaded this stylesheet
     271                 :       }
     272                 :     }
     273                 :   }
     274                 : 
     275               0 :   if (mStyleSheet) {
     276               0 :     doc->BeginUpdate(UPDATE_STYLE);
     277               0 :     doc->RemoveStyleSheet(mStyleSheet);
     278               0 :     doc->EndUpdate(UPDATE_STYLE);
     279               0 :     nsStyleLinkElement::SetStyleSheet(nsnull);
     280                 :   }
     281                 : 
     282               0 :   if (!uri && !isInline) {
     283               0 :     return NS_OK; // If href is empty and this is not inline style then just bail
     284                 :   }
     285                 : 
     286               0 :   nsAutoString title, type, media;
     287                 :   bool isAlternate;
     288                 : 
     289               0 :   GetStyleSheetInfo(title, type, media, &isAlternate);
     290                 : 
     291               0 :   if (!type.LowerCaseEqualsLiteral("text/css")) {
     292               0 :     return NS_OK;
     293                 :   }
     294                 : 
     295               0 :   bool doneLoading = false;
     296               0 :   nsresult rv = NS_OK;
     297               0 :   if (isInline) {
     298               0 :     nsAutoString text;
     299               0 :     nsContentUtils::GetNodeTextContent(thisContent, false, text);
     300                 : 
     301                 :     // Parse the style sheet.
     302                 :     rv = doc->CSSLoader()->
     303                 :       LoadInlineStyle(thisContent, text, mLineNumber, title, media,
     304               0 :                       aObserver, &doneLoading, &isAlternate);
     305                 :   }
     306                 :   else {
     307                 :     // XXXbz clone the URI here to work around content policies modifying URIs.
     308               0 :     nsCOMPtr<nsIURI> clonedURI;
     309               0 :     uri->Clone(getter_AddRefs(clonedURI));
     310               0 :     NS_ENSURE_TRUE(clonedURI, NS_ERROR_OUT_OF_MEMORY);
     311                 :     rv = doc->CSSLoader()->
     312                 :       LoadStyleLink(thisContent, clonedURI, title, media, isAlternate, aObserver,
     313               0 :                     &isAlternate);
     314               0 :     if (NS_FAILED(rv)) {
     315                 :       // Don't propagate LoadStyleLink() errors further than this, since some
     316                 :       // consumers (e.g. nsXMLContentSink) will completely abort on innocuous
     317                 :       // things like a stylesheet load being blocked by the security system.
     318               0 :       doneLoading = true;
     319               0 :       isAlternate = false;
     320               0 :       rv = NS_OK;
     321                 :     }
     322                 :   }
     323                 : 
     324               0 :   NS_ENSURE_SUCCESS(rv, rv);
     325                 : 
     326               0 :   *aWillNotify = !doneLoading;
     327               0 :   *aIsAlternate = isAlternate;
     328                 : 
     329               0 :   return NS_OK;
     330                 : }

Generated by: LCOV version 1.7