Bug 523496: DeCOMtaminate nsCSSParser. r=bzbarsky sr=dbaron

--HG--
rename : layout/style/nsICSSParser.h => layout/style/nsCSSParser.h
This commit is contained in:
Zack Weinberg 2010-03-02 12:59:32 -08:00
parent 93bf95ec1c
commit 1fdb0388ba
23 changed files with 1028 additions and 1075 deletions

View File

@ -152,7 +152,7 @@
#include "mozAutoDocUpdate.h"
#include "nsICSSParser.h"
#include "nsCSSParser.h"
#ifdef MOZ_SVG
#include "nsSVGFeatures.h"
@ -5121,16 +5121,14 @@ ParseSelectorList(nsINode* aNode,
nsIDocument* doc = aNode->GetOwnerDoc();
NS_ENSURE_STATE(doc);
nsCOMPtr<nsICSSParser> parser;
nsresult rv = doc->CSSLoader()->GetParserFor(nsnull, getter_AddRefs(parser));
NS_ENSURE_SUCCESS(rv, rv);
nsCSSParser parser(doc->CSSLoader());
NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
nsCSSSelectorList* selectorList;
rv = parser->ParseSelectorString(aSelectorString,
doc->GetDocumentURI(),
0, // XXXbz get the right line number!
&selectorList);
doc->CSSLoader()->RecycleParser(parser);
nsresult rv = parser.ParseSelectorString(aSelectorString,
doc->GetDocumentURI(),
0, // XXXbz get the line number!
&selectorList);
NS_ENSURE_SUCCESS(rv, rv);
// Filter out pseudo-element selectors from selectorList

View File

@ -48,7 +48,7 @@
#include "nsServiceManagerUtils.h"
#include "nsIDocument.h"
#include "nsICSSStyleRule.h"
#include "nsICSSParser.h"
#include "nsCSSParser.h"
#include "nsICSSLoader.h"
#include "nsIDOMMutationEvent.h"
@ -224,7 +224,6 @@ nsStyledElement::ParseStyleAttribute(const nsAString& aValue,
nsAttrValue& aResult,
PRBool aForceInDataDoc)
{
nsresult result = NS_OK;
nsIDocument* doc = GetOwnerDoc();
if (doc && (aForceInDataDoc ||
@ -244,18 +243,15 @@ nsStyledElement::ParseStyleAttribute(const nsAString& aValue,
if (isCSS) {
nsICSSLoader* cssLoader = doc->CSSLoader();
nsCOMPtr<nsICSSParser> cssParser;
result = cssLoader->GetParserFor(nsnull, getter_AddRefs(cssParser));
nsCSSParser cssParser(cssLoader);
if (cssParser) {
nsCOMPtr<nsIURI> baseURI = GetBaseURI();
nsCOMPtr<nsICSSStyleRule> rule;
result = cssParser->ParseStyleAttribute(aValue, doc->GetDocumentURI(),
baseURI,
NodePrincipal(),
getter_AddRefs(rule));
cssLoader->RecycleParser(cssParser);
cssParser.ParseStyleAttribute(aValue, doc->GetDocumentURI(),
baseURI,
NodePrincipal(),
getter_AddRefs(rule));
if (rule) {
aResult.SetTo(rule);
return;

View File

@ -63,7 +63,7 @@
#include "nsDOMError.h"
#include "nsIScriptError.h"
#include "nsICSSParser.h"
#include "nsCSSParser.h"
#include "nsICSSStyleRule.h"
#include "nsComputedDOMStyle.h"
#include "nsStyleSet.h"
@ -165,8 +165,8 @@ class nsCanvasGradient : public nsIDOMCanvasGradient
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASGRADIENT_PRIVATE_IID)
nsCanvasGradient(gfxPattern* pat, nsICSSParser* cssparser)
: mPattern(pat), mCSSParser(cssparser)
nsCanvasGradient(gfxPattern* pat)
: mPattern(pat)
{
}
@ -186,7 +186,9 @@ public:
if (offset < 0.0 || offset > 1.0)
return NS_ERROR_DOM_INDEX_SIZE_ERR;
nsresult rv = mCSSParser->ParseColorString(nsString(colorstr), nsnull, 0, &color);
nsCSSParser parser;
nsresult rv = parser.ParseColorString(nsString(colorstr),
nsnull, 0, &color);
if (NS_FAILED(rv))
return NS_ERROR_DOM_SYNTAX_ERR;
@ -199,7 +201,6 @@ public:
protected:
nsRefPtr<gfxPattern> mPattern;
nsCOMPtr<nsICSSParser> mCSSParser;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsCanvasGradient, NS_CANVASGRADIENT_PRIVATE_IID)
@ -393,9 +394,6 @@ protected:
// If mCanvasElement is not provided, then a docshell is
nsCOMPtr<nsIDocShell> mDocShell;
// our CSS parser, for colors and whatnot
nsCOMPtr<nsICSSParser> mCSSParser;
// yay thebes
nsRefPtr<gfxContext> mThebes;
nsRefPtr<gfxASurface> mSurface;
@ -731,7 +729,8 @@ nsCanvasRenderingContext2D::SetStyleFromVariant(nsIVariant* aStyle, Style aWhich
}
NS_ENSURE_SUCCESS(rv, rv);
rv = mCSSParser->ParseColorString(str, nsnull, 0, &color);
nsCSSParser parser;
rv = parser.ParseColorString(str, nsnull, 0, &color);
if (NS_FAILED(rv)) {
// Error reporting happens inside the CSS parser
return NS_OK;
@ -927,11 +926,6 @@ nsCanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *docShell, gfxASur
mValid = PR_TRUE;
}
// set up our css parser, if necessary
if (!mCSSParser) {
mCSSParser = do_CreateInstance("@mozilla.org/content/css-parser;1");
}
// set up the initial canvas defaults
mStyleStack.Clear();
mSaveCount = 0;
@ -1297,7 +1291,7 @@ nsCanvasRenderingContext2D::CreateLinearGradient(float x0, float y0, float x1, f
if (!gradpat)
return NS_ERROR_OUT_OF_MEMORY;
nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasGradient(gradpat, mCSSParser);
nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasGradient(gradpat);
if (!grad)
return NS_ERROR_OUT_OF_MEMORY;
@ -1316,7 +1310,7 @@ nsCanvasRenderingContext2D::CreateRadialGradient(float x0, float y0, float r0, f
if (!gradpat)
return NS_ERROR_OUT_OF_MEMORY;
nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasGradient(gradpat, mCSSParser);
nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasGradient(gradpat);
if (!grad)
return NS_ERROR_OUT_OF_MEMORY;
@ -1423,9 +1417,9 @@ nsCanvasRenderingContext2D::GetShadowBlur(float *blur)
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetShadowColor(const nsAString& colorstr)
{
nsCSSParser parser;
nscolor color;
nsresult rv = mCSSParser->ParseColorString(nsString(colorstr), nsnull, 0, &color);
nsresult rv = parser.ParseColorString(colorstr, nsnull, 0, &color);
if (NS_FAILED(rv)) {
// Error reporting happens inside the CSS parser
return NS_OK;
@ -1850,61 +1844,40 @@ nsCanvasRenderingContext2D::Rect(float x, float y, float w, float h)
/**
* Helper function for SetFont that creates a style rule for the given font.
* @param aFont The CSS font string
* @param aCSSParser The CSS parser of the canvas rendering context
* @param aNode The canvas element
* @param aResult Pointer in which to place the new style rule.
* @remark Assumes all pointer arguments are non-null.
*/
static nsresult
CreateFontStyleRule(const nsAString& aFont,
nsICSSParser* aCSSParser,
nsINode* aNode,
nsICSSStyleRule** aResult)
{
nsresult rv;
nsCSSParser parser;
NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsICSSStyleRule> rule;
PRBool changed;
// aFont is to be parsed as the value of a CSS 'font' shorthand,
// and then any line-height setting in that shorthand is to be
// overridden with "normal". Because of the way style rules are
// stored, it is more efficient to fabricate a text string that
// can be processed in one go with ParseStyleAttribute than to
// make two calls to ParseDeclaration.
nsAutoString styleAttr(NS_LITERAL_STRING("font:"));
styleAttr.Append(aFont);
styleAttr.AppendLiteral(";line-height:normal");
nsIPrincipal* principal = aNode->NodePrincipal();
nsIDocument* document = aNode->GetOwnerDoc();
nsIURI* docURL = document->GetDocumentURI();
nsIURI* baseURL = document->GetBaseURI();
rv = aCSSParser->ParseStyleAttribute(
EmptyString(),
docURL,
baseURL,
principal,
getter_AddRefs(rule));
nsresult rv = parser.ParseStyleAttribute(styleAttr, docURL, baseURL,
principal, aResult);
if (NS_FAILED(rv))
return rv;
rv = aCSSParser->ParseProperty(eCSSProperty_font,
aFont,
docURL,
baseURL,
principal,
rule->GetDeclaration(),
&changed);
if (NS_FAILED(rv))
return rv;
// set line height to normal, as per spec
rv = aCSSParser->ParseProperty(eCSSProperty_line_height,
NS_LITERAL_STRING("normal"),
docURL,
baseURL,
principal,
rule->GetDeclaration(),
&changed);
if (NS_FAILED(rv))
return rv;
rule->RuleMatched();
rule.forget(aResult);
(*aResult)->RuleMatched();
return NS_OK;
}
@ -1935,7 +1908,7 @@ nsCanvasRenderingContext2D::SetFont(const nsAString& font)
nsCOMArray<nsIStyleRule> rules;
nsCOMPtr<nsICSSStyleRule> rule;
rv = CreateFontStyleRule(font, mCSSParser.get(), document, getter_AddRefs(rule));
rv = CreateFontStyleRule(font, document, getter_AddRefs(rule));
if (NS_FAILED(rv))
return rv;
@ -1957,7 +1930,6 @@ nsCanvasRenderingContext2D::SetFont(const nsAString& font)
// otherwise inherit from default (10px sans-serif)
nsCOMPtr<nsICSSStyleRule> parentRule;
rv = CreateFontStyleRule(NS_LITERAL_STRING("10px sans-serif"),
mCSSParser.get(),
document,
getter_AddRefs(parentRule));
if (NS_FAILED(rv))
@ -3293,8 +3265,10 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, float aX, float aY
return NS_ERROR_FAILURE;
nscolor bgColor;
nsresult rv = mCSSParser->ParseColorString(PromiseFlatString(aBGColor),
nsnull, 0, &bgColor);
nsCSSParser parser;
NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = parser.ParseColorString(PromiseFlatString(aBGColor),
nsnull, 0, &bgColor);
NS_ENSURE_SUCCESS(rv, rv);
nsIPresShell* presShell = presContext->PresShell();

View File

@ -41,7 +41,6 @@
#include "nsCOMPtr.h"
#include "nsIAtom.h"
#include "nsIContentViewer.h"
#include "nsICSSParser.h"
#include "nsICSSLoader.h"
#include "nsICSSStyleRule.h"
#include "nsCSSStruct.h"

View File

@ -60,7 +60,7 @@
#include "nsRuleWalker.h"
#include "nsCSSDeclaration.h"
#include "nsCSSProps.h"
#include "nsICSSParser.h"
#include "nsCSSParser.h"
#include "nsICSSLoader.h"
#include "nsGenericHTMLElement.h"
#include "nsNodeInfoManager.h"
@ -1035,30 +1035,47 @@ void
nsSVGElement::UpdateContentStyleRule()
{
NS_ASSERTION(!mContentStyleRule, "we already have a content style rule");
PRUint32 attrCount = mAttrsAndChildren.AttrCount();
if (!attrCount) {
// nothing to do
return;
}
nsIDocument* doc = GetOwnerDoc();
if (!doc) {
NS_ERROR("SVG element without owner document");
return;
}
// Try to fetch the CSS Parser from the document.
nsCSSParser parser(doc->CSSLoader());
if (!parser) {
NS_WARNING("failed to get a css parser");
return;
}
// SVG and CSS differ slightly in their interpretation of some of
// the attributes. SVG allows attributes of the form: font-size="5"
// (style="font-size: 5" if using a style attribute)
// where CSS requires units: font-size="5pt" (style="font-size: 5pt")
// Set a flag to pass information to the parser so that we can use
// the CSS parser to parse the font-size attribute. Note that this
// does *not* affect the use of CSS stylesheets, which will still
// require units.
parser.SetSVGMode(PR_TRUE);
nsCOMPtr<nsIURI> baseURI = GetBaseURI();
nsIURI *docURI = doc->GetDocumentURI();
nsICSSLoader* cssLoader = doc->CSSLoader();
nsCSSDeclaration* declaration = nsnull;
nsCOMPtr<nsICSSParser> parser;
nsresult rv = NS_OK;
PRUint32 attrCount = mAttrsAndChildren.AttrCount();
for (PRUint32 i = 0; i < attrCount; ++i) {
const nsAttrName* attrName = mAttrsAndChildren.AttrNameAt(i);
if (!attrName->IsAtom() || !IsAttributeMapped(attrName->Atom()))
continue;
// Create the nsCSSDeclaration if we haven't already.
if (!declaration) {
// Create the nsCSSDeclaration.
declaration = new nsCSSDeclaration();
if (!declaration) {
NS_WARNING("Failed to allocate nsCSSDeclaration");
@ -1069,24 +1086,6 @@ nsSVGElement::UpdateContentStyleRule()
declaration->RuleAbort(); // deletes declaration
return;
}
// Try to fetch the CSS Parser from the document.
rv = cssLoader->GetParserFor(nsnull, getter_AddRefs(parser));
if (NS_FAILED(rv)) {
NS_WARNING("failed to get a css parser");
declaration->RuleAbort(); // deletes declaration
return;
}
// SVG and CSS differ slightly in their interpretation of some of
// the attributes. SVG allows attributes of the form: font-size="5"
// (style="font-size: 5" if using a style attribute)
// where CSS requires units: font-size="5pt" (style="font-size: 5pt")
// Set a flag to pass information to the parser so that we can use
// the CSS parser to parse the font-size attribute. Note that this
// does *not* affect the use of CSS stylesheets, which will still
// require units.
parser->SetSVGMode(PR_TRUE);
}
nsAutoString name;
@ -1096,21 +1095,18 @@ nsSVGElement::UpdateContentStyleRule()
mAttrsAndChildren.AttrAt(i)->ToString(value);
PRBool changed;
parser->ParseProperty(nsCSSProps::LookupProperty(name), value,
docURI, baseURI, NodePrincipal(),
declaration, &changed);
parser.ParseProperty(nsCSSProps::LookupProperty(name), value,
docURI, baseURI, NodePrincipal(),
declaration, &changed);
}
if (declaration) {
rv = NS_NewCSSStyleRule(getter_AddRefs(mContentStyleRule), nsnull, declaration);
nsresult rv = NS_NewCSSStyleRule(getter_AddRefs(mContentStyleRule),
nsnull, declaration);
if (NS_FAILED(rv)) {
NS_WARNING("could not create contentstylerule");
declaration->RuleAbort(); // deletes declaration
}
// Recycle the parser
parser->SetSVGMode(PR_FALSE);
cssLoader->RecycleParser(parser);
}
}

View File

@ -43,7 +43,6 @@
#include "nsXBLDocumentInfo.h"
#include "nsXBLPrototypeHandler.h"
#include "nsXBLProtoImpl.h"
#include "nsICSSParser.h"
#include "nsLayoutCID.h"
/*

View File

@ -123,6 +123,7 @@
#include "nsIDOMViewCSS.h"
#include "nsIDOMCSSStyleDeclaration.h"
#include "nsCSSDeclaration.h"
#include "nsCSSParser.h"
#include "nsIListBoxObject.h"
#include "nsContentUtils.h"
#include "nsContentList.h"
@ -156,7 +157,6 @@
#include "nsCCUncollectableMarker.h"
// Global object maintenance
nsICSSParser* nsXULPrototypeElement::sCSSParser = nsnull;
nsIXBLService * nsXULElement::gXBLService = nsnull;
/**
@ -2753,23 +2753,24 @@ nsXULPrototypeElement::SetAttrAt(PRUint32 aPos, const nsAString& aValue,
mHasClassAttribute = PR_TRUE;
// Compute the element's class list
mAttributes[aPos].mValue.ParseAtomArray(aValue);
return NS_OK;
}
else if (mAttributes[aPos].mName.Equals(nsGkAtoms::style)) {
mHasStyleAttribute = PR_TRUE;
// Parse the element's 'style' attribute
nsCOMPtr<nsICSSStyleRule> rule;
nsICSSParser* parser = GetCSSParser();
nsCSSParser parser;
NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
// XXX Get correct Base URI (need GetBaseURI on *prototype* element)
parser->ParseStyleAttribute(aValue, aDocumentURI, aDocumentURI,
// This is basically duplicating what
// nsINode::NodePrincipal() does
mNodeInfo->NodeInfoManager()->
DocumentPrincipal(),
getter_AddRefs(rule));
parser.ParseStyleAttribute(aValue, aDocumentURI, aDocumentURI,
// This is basically duplicating what
// nsINode::NodePrincipal() does
mNodeInfo->NodeInfoManager()->
DocumentPrincipal(),
getter_AddRefs(rule));
if (rule) {
mAttributes[aPos].mValue.SetTo(rule);

View File

@ -55,7 +55,6 @@
#include "nsIAtom.h"
#include "nsINodeInfo.h"
#include "nsIControllers.h"
#include "nsICSSParser.h"
#include "nsIDOMElement.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOM3EventTarget.h"
@ -302,23 +301,6 @@ public:
// (eg, when a node from an overlay ends up in our document, that node
// must use its original script language, not our document's default.
PRUint16 mScriptTypeID;
static void ReleaseGlobals()
{
NS_IF_RELEASE(sCSSParser);
}
protected:
static nsICSSParser* GetCSSParser()
{
if (!sCSSParser) {
CallCreateInstance(kCSSParserCID, &sCSSParser);
if (sCSSParser) {
sCSSParser->SetQuirkMode(PR_FALSE);
}
}
return sCSSParser;
}
static nsICSSParser* sCSSParser;
};
class nsXULDocument;

View File

@ -47,7 +47,6 @@
#include "nsHTMLParts.h"
#include "nsGenericHTMLElement.h"
#include "nsICSSLoader.h"
#include "nsICSSParser.h"
#include "nsICategoryManager.h"
#include "nsIComponentManager.h"
#include "nsIContentIterator.h"
@ -484,7 +483,6 @@ MAKE_CTOR(CreateXMLDocument, nsIDocument, NS_NewXML
MAKE_CTOR(CreateSVGDocument, nsIDocument, NS_NewSVGDocument)
#endif
MAKE_CTOR(CreateImageDocument, nsIDocument, NS_NewImageDocument)
MAKE_CTOR(CreateCSSParser, nsICSSParser, NS_NewCSSParser)
MAKE_CTOR(CreateCSSLoader, nsICSSLoader, NS_NewCSSLoader)
MAKE_CTOR(CreateDOMSelection, nsISelection, NS_NewDomSelection)
MAKE_CTOR(CreateSelection, nsFrameSelection, NS_NewSelection)
@ -1048,11 +1046,6 @@ static const nsModuleComponentInfo gComponents[] = {
nsnull,
CreateImageDocument },
{ "CSS parser",
NS_CSSPARSER_CID,
"@mozilla.org/content/css-parser;1",
CreateCSSParser },
{ "CSS loader",
NS_CSS_LOADER_CID,
nsnull,

View File

@ -47,7 +47,7 @@
#include "nsCSSAnonBoxes.h"
#include "nsCSSFrameConstructor.h"
#include "nsCSSKeywords.h"
#include "nsCSSLoader.h"
#include "nsCSSParser.h"
#include "nsCSSProps.h"
#include "nsCSSPseudoClasses.h"
#include "nsCSSPseudoElements.h"
@ -311,7 +311,7 @@ nsLayoutStatics::Shutdown()
nsDOMEventRTTearoff::Shutdown();
nsEventListenerManager::Shutdown();
nsComputedDOMStyle::Shutdown();
CSSLoaderImpl::Shutdown();
nsCSSParser::Shutdown();
nsCSSRuleProcessor::Shutdown();
nsTextFrameTextRunCache::Shutdown();
nsHTMLDNSPrefetch::Shutdown();
@ -333,7 +333,6 @@ nsLayoutStatics::Shutdown()
nsXULContentUtils::Finish();
nsXULElement::ReleaseGlobals();
nsXULPrototypeCache::ReleaseGlobals();
nsXULPrototypeElement::ReleaseGlobals();
nsSprocketLayout::Shutdown();
#endif

View File

@ -57,6 +57,7 @@ EXPORTS = \
nsCSSAnonBoxes.h \
nsCSSKeywordList.h \
nsCSSKeywords.h \
nsCSSParser.h \
nsCSSPropList.h \
nsCSSProperty.h \
nsCSSProps.h \
@ -76,7 +77,6 @@ EXPORTS = \
nsICSSLoader.h \
nsICSSLoaderObserver.h \
nsICSSNameSpaceRule.h \
nsICSSParser.h \
nsICSSPseudoComparator.h \
nsICSSRule.h \
nsICSSRuleList.h \

View File

@ -37,9 +37,10 @@
*
* ***** END LICENSE BLOCK *****
*
* This Original Code has been modified by IBM Corporation. Modifications made by IBM
* described herein are Copyright (c) International Business Machines Corporation, 2000.
* Modifications to Mozilla code or documentation identified per MPL Section 3.3
* This Original Code has been modified by IBM Corporation.
* Modifications made by IBM described herein are Copyright (c)
* International Business Machines Corporation, 2000. Modifications
* to Mozilla code or documentation identified per MPL Section 3.3
*
* Date Modified by Description of modification
* 04/20/2000 IBM Corp. OS/2 VisualAge build.
@ -47,7 +48,19 @@
/* loading of CSS style sheets using the network APIs */
#include "nsCSSLoader.h"
#include "nsICSSLoader.h"
#include "nsIRunnable.h"
#include "nsIUnicharStreamLoader.h"
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "nsString.h"
#include "nsURIHashKey.h"
#include "nsInterfaceHashtable.h"
#include "nsDataHashtable.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "nsIPrincipal.h"
#include "nsTObserverArray.h"
#include "nsIContent.h"
#include "nsIDOMNode.h"
#include "nsIDOMWindow.h"
@ -74,8 +87,7 @@
#include "nsICSSStyleSheet.h"
#include "nsIStyleSheetLinkingElement.h"
#include "nsICSSLoaderObserver.h"
#include "nsICSSLoader.h"
#include "nsICSSParser.h"
#include "nsCSSParser.h"
#include "nsICSSImportRule.h"
#include "nsThreadUtils.h"
#include "nsGkAtoms.h"
@ -92,6 +104,449 @@
#include "nsIDOMCSSImportRule.h"
#include "nsContentErrors.h"
/**
* OVERALL ARCHITECTURE
*
* The CSS Loader gets requests to load various sorts of style sheets:
* inline style from <style> elements, linked style, @import-ed child
* sheets, non-document sheets. The loader handles the following tasks:
*
* 1) Checking whether the load is allowed: CheckLoadAllowed()
* 2) Creation of the actual style sheet objects: CreateSheet()
* 3) setting of the right media, title, enabled state, etc on the
* sheet: PrepareSheet()
* 4) Insertion of the sheet in the proper cascade order:
* InsertSheetInDoc() and InsertChildSheet()
* 5) Load of the sheet: LoadSheet()
* 6) Parsing of the sheet: ParseSheet()
* 7) Cleanup: SheetComplete()
*
* The detailed documentation for these functions is found with the
* function implementations.
*
* The following helper object is used:
* SheetLoadData -- a small class that is used to store all the
* information needed for the loading of a sheet;
* this class handles listening for the stream
* loader completion and also handles charset
* determination.
*/
class CSSLoaderImpl;
/*********************************************
* Data needed to properly load a stylesheet *
*********************************************/
class SheetLoadData : public nsIRunnable,
public nsIUnicharStreamLoaderObserver
{
public:
virtual ~SheetLoadData(void);
// Data for loading a sheet linked from a document
SheetLoadData(CSSLoaderImpl* aLoader,
const nsSubstring& aTitle,
nsIURI* aURI,
nsICSSStyleSheet* aSheet,
nsIStyleSheetLinkingElement* aOwningElement,
PRBool aIsAlternate,
nsICSSLoaderObserver* aObserver,
nsIPrincipal* aLoaderPrincipal);
// Data for loading a sheet linked from an @import rule
SheetLoadData(CSSLoaderImpl* aLoader,
nsIURI* aURI,
nsICSSStyleSheet* aSheet,
SheetLoadData* aParentData,
nsICSSLoaderObserver* aObserver,
nsIPrincipal* aLoaderPrincipal);
// Data for loading a non-document sheet
SheetLoadData(CSSLoaderImpl* aLoader,
nsIURI* aURI,
nsICSSStyleSheet* aSheet,
PRBool aSyncLoad,
PRBool aAllowUnsafeRules,
PRBool aUseSystemPrincipal,
const nsCString& aCharset,
nsICSSLoaderObserver* aObserver,
nsIPrincipal* aLoaderPrincipal);
already_AddRefed<nsIURI> GetReferrerURI();
NS_DECL_ISUPPORTS
NS_DECL_NSIRUNNABLE
NS_DECL_NSIUNICHARSTREAMLOADEROBSERVER
// Hold a ref to the CSSLoader so we can call back to it to let it
// know the load finished
CSSLoaderImpl* mLoader; // strong ref
// Title needed to pull datas out of the pending datas table when
// the preferred title is changed
nsString mTitle;
// Charset we decided to use for the sheet
nsCString mCharset;
// URI we're loading. Null for inline sheets
nsCOMPtr<nsIURI> mURI;
// Should be 1 for non-inline sheets.
PRUint32 mLineNumber;
// The sheet we're loading data for
nsCOMPtr<nsICSSStyleSheet> mSheet;
// Linked list of datas for the same URI as us
SheetLoadData* mNext; // strong ref
// Load data for the sheet that @import-ed us if we were @import-ed
// during the parse
SheetLoadData* mParentData; // strong ref
// Number of sheets we @import-ed that are still loading
PRUint32 mPendingChildren;
// mSyncLoad is true when the load needs to be synchronous -- right
// now only for LoadSheetSync and children of sync loads.
PRPackedBool mSyncLoad : 1;
// mIsNonDocumentSheet is true if the load was triggered by LoadSheetSync or
// LoadSheet or an @import from such a sheet. Non-document sheet loads can
// proceed even if we have no document.
PRPackedBool mIsNonDocumentSheet : 1;
// mIsLoading is true from the moment we are placed in the loader's
// "loading datas" table (right after the async channel is opened)
// to the moment we are removed from said table (due to the load
// completing or being cancelled).
PRPackedBool mIsLoading : 1;
// mIsCancelled is set to true when a sheet load is stopped by
// Stop() or StopLoadingSheet(). SheetLoadData::OnStreamComplete()
// checks this to avoid parsing sheets that have been cancelled and
// such.
PRPackedBool mIsCancelled : 1;
// mMustNotify is true if the load data is being loaded async and
// the original function call that started the load has returned.
// XXXbz sort our relationship with load/error events!
PRPackedBool mMustNotify : 1;
// mWasAlternate is true if the sheet was an alternate when the load data was
// created.
PRPackedBool mWasAlternate : 1;
// mAllowUnsafeRules is true if we should allow unsafe rules to be parsed
// in the loaded sheet.
PRPackedBool mAllowUnsafeRules : 1;
// mUseSystemPrincipal is true if the system principal should be used for
// this sheet, no matter what the channel principal is. Only true for sync
// loads.
PRPackedBool mUseSystemPrincipal : 1;
// This is the element that imported the sheet. Needed to get the
// charset set on it.
nsCOMPtr<nsIStyleSheetLinkingElement> mOwningElement;
// The observer that wishes to be notified of load completion
nsCOMPtr<nsICSSLoaderObserver> mObserver;
// The principal that identifies who started loading us.
nsCOMPtr<nsIPrincipal> mLoaderPrincipal;
// The charset to use if the transport and sheet don't indicate one.
// May be empty. Must be empty if mOwningElement is non-null.
nsCString mCharsetHint;
};
class nsURIAndPrincipalHashKey : public nsURIHashKey
{
public:
typedef nsURIAndPrincipalHashKey* KeyType;
typedef const nsURIAndPrincipalHashKey* KeyTypePointer;
nsURIAndPrincipalHashKey(const nsURIAndPrincipalHashKey* aKey)
: nsURIHashKey(aKey->mKey), mPrincipal(aKey->mPrincipal)
{
MOZ_COUNT_CTOR(nsURIAndPrincipalHashKey);
}
nsURIAndPrincipalHashKey(nsIURI* aURI, nsIPrincipal* aPrincipal)
: nsURIHashKey(aURI), mPrincipal(aPrincipal)
{
MOZ_COUNT_CTOR(nsURIAndPrincipalHashKey);
}
nsURIAndPrincipalHashKey(const nsURIAndPrincipalHashKey& toCopy)
: nsURIHashKey(toCopy), mPrincipal(toCopy.mPrincipal)
{
MOZ_COUNT_CTOR(nsURIAndPrincipalHashKey);
}
~nsURIAndPrincipalHashKey()
{
MOZ_COUNT_DTOR(nsURIAndPrincipalHashKey);
}
nsURIAndPrincipalHashKey* GetKey() const {
return const_cast<nsURIAndPrincipalHashKey*>(this);
}
const nsURIAndPrincipalHashKey* GetKeyPointer() const { return this; }
PRBool KeyEquals(const nsURIAndPrincipalHashKey* aKey) const {
if (!nsURIHashKey::KeyEquals(aKey->mKey)) {
return PR_FALSE;
}
if (!mPrincipal != !aKey->mPrincipal) {
// One or the other has a principal, but not both... not equal
return PR_FALSE;
}
PRBool eq;
return !mPrincipal ||
(NS_SUCCEEDED(mPrincipal->Equals(aKey->mPrincipal, &eq)) && eq);
}
static const nsURIAndPrincipalHashKey*
KeyToPointer(nsURIAndPrincipalHashKey* aKey) { return aKey; }
static PLDHashNumber HashKey(const nsURIAndPrincipalHashKey* aKey) {
return nsURIHashKey::HashKey(aKey->mKey);
}
enum { ALLOW_MEMMOVE = PR_TRUE };
protected:
nsCOMPtr<nsIPrincipal> mPrincipal;
};
/***********************************************************************
* Enum that describes the state of the sheet returned by CreateSheet. *
***********************************************************************/
enum StyleSheetState {
eSheetStateUnknown = 0,
eSheetNeedsParser,
eSheetPending,
eSheetLoading,
eSheetComplete
};
/**********************
* Loader Declaration *
**********************/
class CSSLoaderImpl : public nsICSSLoader
{
public:
CSSLoaderImpl(void);
virtual ~CSSLoaderImpl(void);
NS_DECL_ISUPPORTS
// nsICSSLoader methods
NS_IMETHOD Init(nsIDocument* aDocument);
NS_IMETHOD DropDocumentReference(void);
NS_IMETHOD SetCompatibilityMode(nsCompatibility aCompatMode);
NS_IMETHOD_(nsCompatibility) GetCompatibilityMode();
NS_IMETHOD SetPreferredSheet(const nsAString& aTitle);
NS_IMETHOD GetPreferredSheet(nsAString& aTitle);
NS_IMETHOD LoadInlineStyle(nsIContent* aElement,
nsIUnicharInputStream* aStream,
PRUint32 aLineNumber,
const nsSubstring& aTitle,
const nsSubstring& aMedia,
nsICSSLoaderObserver* aObserver,
PRBool* aCompleted,
PRBool* aIsAlternate);
NS_IMETHOD LoadStyleLink(nsIContent* aElement,
nsIURI* aURL,
const nsSubstring& aTitle,
const nsSubstring& aMedia,
PRBool aHasAlternateRel,
nsICSSLoaderObserver* aObserver,
PRBool* aIsAlternate);
NS_IMETHOD LoadChildSheet(nsICSSStyleSheet* aParentSheet,
nsIURI* aURL,
nsMediaList* aMedia,
nsICSSImportRule* aRule);
NS_IMETHOD LoadSheetSync(nsIURI* aURL, PRBool aAllowUnsafeRules,
PRBool aUseSystemPrincipal,
nsICSSStyleSheet** aSheet);
NS_IMETHOD LoadSheet(nsIURI* aURL,
nsIPrincipal* aOriginPrincipal,
const nsCString& aCharset,
nsICSSLoaderObserver* aObserver,
nsICSSStyleSheet** aSheet);
NS_IMETHOD LoadSheet(nsIURI* aURL,
nsIPrincipal* aOriginPrincipal,
const nsCString& aCharset,
nsICSSLoaderObserver* aObserver);
// stop loading all sheets
NS_IMETHOD Stop(void);
// stop loading one sheet
NS_IMETHOD StopLoadingSheet(nsIURI* aURL);
/**
* Is the loader enabled or not.
* When disabled, processing of new styles is disabled and an attempt
* to do so will fail with a return code of
* NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable
* currently loading styles or already processed styles.
*/
NS_IMETHOD GetEnabled(PRBool *aEnabled);
NS_IMETHOD SetEnabled(PRBool aEnabled);
NS_IMETHOD_(PRBool) HasPendingLoads();
NS_IMETHOD AddObserver(nsICSSLoaderObserver* aObserver);
NS_IMETHOD_(void) RemoveObserver(nsICSSLoaderObserver* aObserver);
// local helper methods (some are public for access from statics)
// IsAlternate can change our currently selected style set if none
// is selected and aHasAlternateRel is false.
PRBool IsAlternate(const nsAString& aTitle, PRBool aHasAlternateRel);
private:
// Note: null aSourcePrincipal indicates that the content policy and
// CheckLoadURI checks should be skipped.
nsresult CheckLoadAllowed(nsIPrincipal* aSourcePrincipal,
nsIURI* aTargetURI,
nsISupports* aContext);
// For inline style, the aURI param is null, but the aLinkingContent
// must be non-null then. The loader principal must never be null
// if aURI is not null.
nsresult CreateSheet(nsIURI* aURI,
nsIContent* aLinkingContent,
nsIPrincipal* aLoaderPrincipal,
PRBool aSyncLoad,
StyleSheetState& aSheetState,
nsICSSStyleSheet** aSheet);
// Pass in either a media string or the nsMediaList from the
// CSSParser. Don't pass both.
// If aIsAlternate is non-null, this method will set *aIsAlternate to
// correspond to the sheet's enabled state (which it will set no matter what)
nsresult PrepareSheet(nsICSSStyleSheet* aSheet,
const nsSubstring& aTitle,
const nsSubstring& aMediaString,
nsMediaList* aMediaList,
PRBool aHasAlternateRel = PR_FALSE,
PRBool *aIsAlternate = nsnull);
nsresult InsertSheetInDoc(nsICSSStyleSheet* aSheet,
nsIContent* aLinkingContent,
nsIDocument* aDocument);
nsresult InsertChildSheet(nsICSSStyleSheet* aSheet,
nsICSSStyleSheet* aParentSheet,
nsICSSImportRule* aParentRule);
nsresult InternalLoadNonDocumentSheet(nsIURI* aURL,
PRBool aAllowUnsafeRules,
PRBool aUseSystemPrincipal,
nsIPrincipal* aOriginPrincipal,
const nsCString& aCharset,
nsICSSStyleSheet** aSheet,
nsICSSLoaderObserver* aObserver);
// Post a load event for aObserver to be notified about aSheet. The
// notification will be sent with status NS_OK unless the load event is
// canceled at some point (in which case it will be sent with
// NS_BINDING_ABORTED). aWasAlternate indicates the state when the load was
// initiated, not the state at some later time. aURI should be the URI the
// sheet was loaded from (may be null for inline sheets).
nsresult PostLoadEvent(nsIURI* aURI,
nsICSSStyleSheet* aSheet,
nsICSSLoaderObserver* aObserver,
PRBool aWasAlternate);
// Start the loads of all the sheets in mPendingDatas
void StartAlternateLoads();
public:
// Handle an event posted by PostLoadEvent
void HandleLoadEvent(SheetLoadData* aEvent);
protected:
// Note: LoadSheet is responsible for releasing aLoadData and setting the
// sheet to complete on failure.
nsresult LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState);
friend class SheetLoadData;
// Protected functions and members are ones that SheetLoadData needs
// access to.
// Parse the stylesheet in aLoadData. The sheet data comes from aStream.
// Set aCompleted to true if the parse finished, false otherwise (e.g. if the
// sheet had an @import). If aCompleted is true when this returns, then
// ParseSheet also called SheetComplete on aLoadData
nsresult ParseSheet(nsIUnicharInputStream* aStream,
SheetLoadData* aLoadData,
PRBool& aCompleted);
// The load of the sheet in aLoadData is done, one way or another. Do final
// cleanup, including releasing aLoadData.
void SheetComplete(SheetLoadData* aLoadData, nsresult aStatus);
public:
typedef nsTArray<nsRefPtr<SheetLoadData> > LoadDataArray;
private:
// The guts of SheetComplete. This may be called recursively on parent datas
// or datas that had glommed on to a single load. The array is there so load
// datas whose observers need to be notified can be added to it.
void DoSheetComplete(SheetLoadData* aLoadData, nsresult aStatus,
LoadDataArray& aDatasToNotify);
// the load data needs access to the document...
nsIDocument* mDocument; // the document we live for
#ifdef DEBUG
PRPackedBool mSyncCallback;
#endif
PRPackedBool mEnabled; // is enabled to load new styles
nsCompatibility mCompatMode;
nsString mPreferredSheet; // title of preferred sheet
nsInterfaceHashtable<nsURIAndPrincipalHashKey,
nsICSSStyleSheet> mCompleteSheets;
nsDataHashtable<nsURIAndPrincipalHashKey,
SheetLoadData*> mLoadingDatas; // weak refs
nsDataHashtable<nsURIAndPrincipalHashKey,
SheetLoadData*> mPendingDatas; // weak refs
// We're not likely to have many levels of @import... But likely to have
// some. Allocate some storage, what the hell.
nsAutoTArray<SheetLoadData*, 8> mParsingDatas;
// The array of posted stylesheet loaded events (SheetLoadDatas) we have.
// Note that these are rare.
LoadDataArray mPostedEvents;
// Number of datas still waiting to be notified on if we're notifying on a
// whole bunch at once (e.g. in one of the stop methods). This is used to
// make sure that HasPendingLoads() won't return false until we're notifying
// on the last data we're working with.
PRUint32 mDatasToNotifyOn;
// Our array of "global" observers
nsTObserverArray<nsCOMPtr<nsICSSLoaderObserver> > mObservers;
};
#ifdef MOZ_LOGGING
// #define FORCE_PR_LOG /* Allow logging in the release build */
#endif /* MOZ_LOGGING */
@ -269,9 +724,6 @@ SheetLoadData::Run()
* Loader Implementation *
*************************/
// static
nsCOMArray<nsICSSParser>* CSSLoaderImpl::gParsers = nsnull;
CSSLoaderImpl::CSSLoaderImpl(void)
: mDocument(nsnull),
mEnabled(PR_TRUE),
@ -293,13 +745,6 @@ CSSLoaderImpl::~CSSLoaderImpl(void)
NS_IMPL_ISUPPORTS1(CSSLoaderImpl, nsICSSLoader)
void
CSSLoaderImpl::Shutdown()
{
delete gParsers;
gParsers = nsnull;
}
NS_IMETHODIMP
CSSLoaderImpl::Init(nsIDocument* aDocument)
{
@ -337,6 +782,12 @@ CSSLoaderImpl::SetCompatibilityMode(nsCompatibility aCompatMode)
return NS_OK;
}
NS_IMETHODIMP_(nsCompatibility)
CSSLoaderImpl::GetCompatibilityMode()
{
return mCompatMode;
}
static PLDHashOperator
CollectNonAlternates(nsURIAndPrincipalHashKey *aKey,
SheetLoadData* &aData,
@ -395,58 +846,6 @@ CSSLoaderImpl::GetPreferredSheet(nsAString& aTitle)
return NS_OK;
}
NS_IMETHODIMP
CSSLoaderImpl::GetParserFor(nsICSSStyleSheet* aSheet,
nsICSSParser** aParser)
{
NS_PRECONDITION(aParser, "Null out param");
*aParser = nsnull;
if (!gParsers) {
gParsers = new nsCOMArray<nsICSSParser>;
if (!gParsers) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
PRInt32 count = gParsers->Count();
if (0 < count--) {
*aParser = gParsers->ObjectAt(count);
NS_ADDREF(*aParser);
gParsers->RemoveObjectAt(count);
}
nsresult result = NS_OK;
if (! *aParser) {
result = NS_NewCSSParser(aParser);
}
if (*aParser) {
(*aParser)->SetQuirkMode(mCompatMode == eCompatibility_NavQuirks);
if (aSheet) {
(*aParser)->SetStyleSheet(aSheet);
}
(*aParser)->SetChildLoader(this);
}
return result;
}
NS_IMETHODIMP
CSSLoaderImpl::RecycleParser(nsICSSParser* aParser)
{
NS_PRECONDITION(aParser, "Recycle only good parsers, please");
NS_ENSURE_TRUE(gParsers, NS_ERROR_UNEXPECTED);
if (!gParsers->AppendObject(aParser)) {
return NS_ERROR_FAILURE;
}
// Make sure the parser doesn't keep the last sheet it parsed alive
aParser->SetStyleSheet(nsnull);
return NS_OK;
}
static const char kCharsetSym[] = "@charset \"";
@ -1141,15 +1540,15 @@ CSSLoaderImpl::PrepareSheet(nsICSSStyleSheet* aSheet,
"must not provide both aMediaString and aMediaList");
mediaList = new nsMediaList();
NS_ENSURE_TRUE(mediaList, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsICSSParser> mediumParser;
nsresult rv = GetParserFor(nsnull, getter_AddRefs(mediumParser));
NS_ENSURE_SUCCESS(rv, rv);
nsCSSParser mediumParser(this);
NS_ENSURE_TRUE(mediumParser, NS_ERROR_OUT_OF_MEMORY);
// We have aMediaString only when linked from link elements, style
// elements, or PIs, so pass PR_TRUE.
rv = mediumParser->ParseMediaList(aMediaString, nsnull, 0, mediaList,
PR_TRUE);
rv = mediumParser.ParseMediaList(aMediaString, nsnull, 0, mediaList,
PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
RecycleParser(mediumParser);
}
rv = aSheet->SetMedia(mediaList);
@ -1540,12 +1939,11 @@ CSSLoaderImpl::ParseSheet(nsIUnicharInputStream* aStream,
aCompleted = PR_FALSE;
nsCOMPtr<nsICSSParser> parser;
nsresult rv = GetParserFor(aLoadData->mSheet, getter_AddRefs(parser));
if (NS_FAILED(rv)) {
nsCSSParser parser(this, aLoadData->mSheet);
if (!parser) {
LOG_ERROR((" Failed to get CSS parser"));
SheetComplete(aLoadData, rv);
return rv;
SheetComplete(aLoadData, NS_ERROR_OUT_OF_MEMORY);
return NS_ERROR_OUT_OF_MEMORY;
}
// Push our load data on the stack so any kids can pick it up
@ -1553,15 +1951,21 @@ CSSLoaderImpl::ParseSheet(nsIUnicharInputStream* aStream,
nsCOMPtr<nsIURI> sheetURI, baseURI;
aLoadData->mSheet->GetSheetURI(getter_AddRefs(sheetURI));
aLoadData->mSheet->GetBaseURI(getter_AddRefs(baseURI));
rv = parser->Parse(aStream, sheetURI, baseURI,
aLoadData->mSheet->Principal(), aLoadData->mLineNumber,
aLoadData->mAllowUnsafeRules);
nsresult rv = parser.Parse(aStream, sheetURI, baseURI,
aLoadData->mSheet->Principal(),
aLoadData->mLineNumber,
aLoadData->mAllowUnsafeRules);
mParsingDatas.RemoveElementAt(mParsingDatas.Length() - 1);
RecycleParser(parser);
if (NS_FAILED(rv)) {
LOG_ERROR((" Low-level error in parser!"));
SheetComplete(aLoadData, rv);
return rv;
}
NS_ASSERTION(aLoadData->mPendingChildren == 0 || !aLoadData->mSyncLoad,
"Sync load has leftover pending children!");
if (aLoadData->mPendingChildren == 0) {
LOG((" No pending kids from parse"));
aCompleted = PR_TRUE;
@ -1569,7 +1973,7 @@ CSSLoaderImpl::ParseSheet(nsIUnicharInputStream* aStream,
}
// Otherwise, the children are holding strong refs to the data and
// will call SheetComplete() on it when they complete.
return NS_OK;
}

View File

@ -1,525 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: ft=cpp tw=78 sw=2 et ts=2
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Boris Zbarsky <bzbarsky@mit.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK *****
*
* This Original Code has been modified by IBM Corporation. Modifications made by IBM
* described herein are Copyright (c) International Business Machines Corporation, 2000.
* Modifications to Mozilla code or documentation identified per MPL Section 3.3
*
* Date Modified by Description of modification
* 04/20/2000 IBM Corp. OS/2 VisualAge build.
*/
/* loading of CSS style sheets using the network APIs */
#ifndef nsCSSLoader_h__
#define nsCSSLoader_h__
class CSSLoaderImpl;
class nsIURI;
class nsICSSStyleSheet;
class nsIStyleSheetLinkingElement;
class nsICSSLoaderObserver;
class nsICSSParser;
class nsICSSImportRule;
class nsMediaList;
#include "nsICSSLoader.h"
#include "nsIRunnable.h"
#include "nsIUnicharStreamLoader.h"
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "nsString.h"
#include "nsURIHashKey.h"
#include "nsInterfaceHashtable.h"
#include "nsDataHashtable.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "nsIPrincipal.h"
#include "nsTObserverArray.h"
/**
* OVERALL ARCHITECTURE
*
* The CSS Loader gets requests to load various sorts of style sheets:
* inline style from <style> elements, linked style, @import-ed child
* sheets, non-document sheets. The loader handles the following tasks:
*
* 1) Checking whether the load is allowed: CheckLoadAllowed()
* 2) Creation of the actual style sheet objects: CreateSheet()
* 3) setting of the right media, title, enabled state, etc on the
* sheet: PrepareSheet()
* 4) Insertion of the sheet in the proper cascade order:
* InsertSheetInDoc() and InsertChildSheet()
* 5) Load of the sheet: LoadSheet()
* 6) Parsing of the sheet: ParseSheet()
* 7) Cleanup: SheetComplete()
*
* The detailed documentation for these functions is found with the
* function implementations.
*
* The following helper object is used:
* SheetLoadData -- a small class that is used to store all the
* information needed for the loading of a sheet;
* this class handles listening for the stream
* loader completion and also handles charset
* determination.
*/
/*********************************************
* Data needed to properly load a stylesheet *
*********************************************/
class SheetLoadData : public nsIRunnable,
public nsIUnicharStreamLoaderObserver
{
public:
virtual ~SheetLoadData(void);
// Data for loading a sheet linked from a document
SheetLoadData(CSSLoaderImpl* aLoader,
const nsSubstring& aTitle,
nsIURI* aURI,
nsICSSStyleSheet* aSheet,
nsIStyleSheetLinkingElement* aOwningElement,
PRBool aIsAlternate,
nsICSSLoaderObserver* aObserver,
nsIPrincipal* aLoaderPrincipal);
// Data for loading a sheet linked from an @import rule
SheetLoadData(CSSLoaderImpl* aLoader,
nsIURI* aURI,
nsICSSStyleSheet* aSheet,
SheetLoadData* aParentData,
nsICSSLoaderObserver* aObserver,
nsIPrincipal* aLoaderPrincipal);
// Data for loading a non-document sheet
SheetLoadData(CSSLoaderImpl* aLoader,
nsIURI* aURI,
nsICSSStyleSheet* aSheet,
PRBool aSyncLoad,
PRBool aAllowUnsafeRules,
PRBool aUseSystemPrincipal,
const nsCString& aCharset,
nsICSSLoaderObserver* aObserver,
nsIPrincipal* aLoaderPrincipal);
already_AddRefed<nsIURI> GetReferrerURI();
NS_DECL_ISUPPORTS
NS_DECL_NSIRUNNABLE
NS_DECL_NSIUNICHARSTREAMLOADEROBSERVER
// Hold a ref to the CSSLoader so we can call back to it to let it
// know the load finished
CSSLoaderImpl* mLoader; // strong ref
// Title needed to pull datas out of the pending datas table when
// the preferred title is changed
nsString mTitle;
// Charset we decided to use for the sheet
nsCString mCharset;
// URI we're loading. Null for inline sheets
nsCOMPtr<nsIURI> mURI;
// Should be 1 for non-inline sheets.
PRUint32 mLineNumber;
// The sheet we're loading data for
nsCOMPtr<nsICSSStyleSheet> mSheet;
// Linked list of datas for the same URI as us
SheetLoadData* mNext; // strong ref
// Load data for the sheet that @import-ed us if we were @import-ed
// during the parse
SheetLoadData* mParentData; // strong ref
// Number of sheets we @import-ed that are still loading
PRUint32 mPendingChildren;
// mSyncLoad is true when the load needs to be synchronous -- right
// now only for LoadSheetSync and children of sync loads.
PRPackedBool mSyncLoad : 1;
// mIsNonDocumentSheet is true if the load was triggered by LoadSheetSync or
// LoadSheet or an @import from such a sheet. Non-document sheet loads can
// proceed even if we have no document.
PRPackedBool mIsNonDocumentSheet : 1;
// mIsLoading is true from the moment we are placed in the loader's
// "loading datas" table (right after the async channel is opened)
// to the moment we are removed from said table (due to the load
// completing or being cancelled).
PRPackedBool mIsLoading : 1;
// mIsCancelled is set to true when a sheet load is stopped by
// Stop() or StopLoadingSheet(). SheetLoadData::OnStreamComplete()
// checks this to avoid parsing sheets that have been cancelled and
// such.
PRPackedBool mIsCancelled : 1;
// mMustNotify is true if the load data is being loaded async and
// the original function call that started the load has returned.
// XXXbz sort our relationship with load/error events!
PRPackedBool mMustNotify : 1;
// mWasAlternate is true if the sheet was an alternate when the load data was
// created.
PRPackedBool mWasAlternate : 1;
// mAllowUnsafeRules is true if we should allow unsafe rules to be parsed
// in the loaded sheet.
PRPackedBool mAllowUnsafeRules : 1;
// mUseSystemPrincipal is true if the system principal should be used for
// this sheet, no matter what the channel principal is. Only true for sync
// loads.
PRPackedBool mUseSystemPrincipal : 1;
// This is the element that imported the sheet. Needed to get the
// charset set on it.
nsCOMPtr<nsIStyleSheetLinkingElement> mOwningElement;
// The observer that wishes to be notified of load completion
nsCOMPtr<nsICSSLoaderObserver> mObserver;
// The principal that identifies who started loading us.
nsCOMPtr<nsIPrincipal> mLoaderPrincipal;
// The charset to use if the transport and sheet don't indicate one.
// May be empty. Must be empty if mOwningElement is non-null.
nsCString mCharsetHint;
};
class nsURIAndPrincipalHashKey : public nsURIHashKey
{
public:
typedef nsURIAndPrincipalHashKey* KeyType;
typedef const nsURIAndPrincipalHashKey* KeyTypePointer;
nsURIAndPrincipalHashKey(const nsURIAndPrincipalHashKey* aKey)
: nsURIHashKey(aKey->mKey), mPrincipal(aKey->mPrincipal)
{
MOZ_COUNT_CTOR(nsURIAndPrincipalHashKey);
}
nsURIAndPrincipalHashKey(nsIURI* aURI, nsIPrincipal* aPrincipal)
: nsURIHashKey(aURI), mPrincipal(aPrincipal)
{
MOZ_COUNT_CTOR(nsURIAndPrincipalHashKey);
}
nsURIAndPrincipalHashKey(const nsURIAndPrincipalHashKey& toCopy)
: nsURIHashKey(toCopy), mPrincipal(toCopy.mPrincipal)
{
MOZ_COUNT_CTOR(nsURIAndPrincipalHashKey);
}
~nsURIAndPrincipalHashKey()
{
MOZ_COUNT_DTOR(nsURIAndPrincipalHashKey);
}
nsURIAndPrincipalHashKey* GetKey() const {
return const_cast<nsURIAndPrincipalHashKey*>(this);
}
const nsURIAndPrincipalHashKey* GetKeyPointer() const { return this; }
PRBool KeyEquals(const nsURIAndPrincipalHashKey* aKey) const {
if (!nsURIHashKey::KeyEquals(aKey->mKey)) {
return PR_FALSE;
}
if (!mPrincipal != !aKey->mPrincipal) {
// One or the other has a principal, but not both... not equal
return PR_FALSE;
}
PRBool eq;
return !mPrincipal ||
(NS_SUCCEEDED(mPrincipal->Equals(aKey->mPrincipal, &eq)) && eq);
}
static const nsURIAndPrincipalHashKey*
KeyToPointer(nsURIAndPrincipalHashKey* aKey) { return aKey; }
static PLDHashNumber HashKey(const nsURIAndPrincipalHashKey* aKey) {
return nsURIHashKey::HashKey(aKey->mKey);
}
enum { ALLOW_MEMMOVE = PR_TRUE };
protected:
nsCOMPtr<nsIPrincipal> mPrincipal;
};
/***********************************************************************
* Enum that describes the state of the sheet returned by CreateSheet. *
***********************************************************************/
enum StyleSheetState {
eSheetStateUnknown = 0,
eSheetNeedsParser,
eSheetPending,
eSheetLoading,
eSheetComplete
};
/**********************
* Loader Declaration *
**********************/
class CSSLoaderImpl : public nsICSSLoader
{
public:
CSSLoaderImpl(void);
virtual ~CSSLoaderImpl(void);
NS_DECL_ISUPPORTS
static void Shutdown(); // called at app shutdown
// nsICSSLoader methods
NS_IMETHOD Init(nsIDocument* aDocument);
NS_IMETHOD DropDocumentReference(void);
NS_IMETHOD SetCompatibilityMode(nsCompatibility aCompatMode);
NS_IMETHOD SetPreferredSheet(const nsAString& aTitle);
NS_IMETHOD GetPreferredSheet(nsAString& aTitle);
NS_IMETHOD GetParserFor(nsICSSStyleSheet* aSheet,
nsICSSParser** aParser);
NS_IMETHOD RecycleParser(nsICSSParser* aParser);
NS_IMETHOD LoadInlineStyle(nsIContent* aElement,
nsIUnicharInputStream* aStream,
PRUint32 aLineNumber,
const nsSubstring& aTitle,
const nsSubstring& aMedia,
nsICSSLoaderObserver* aObserver,
PRBool* aCompleted,
PRBool* aIsAlternate);
NS_IMETHOD LoadStyleLink(nsIContent* aElement,
nsIURI* aURL,
const nsSubstring& aTitle,
const nsSubstring& aMedia,
PRBool aHasAlternateRel,
nsICSSLoaderObserver* aObserver,
PRBool* aIsAlternate);
NS_IMETHOD LoadChildSheet(nsICSSStyleSheet* aParentSheet,
nsIURI* aURL,
nsMediaList* aMedia,
nsICSSImportRule* aRule);
NS_IMETHOD LoadSheetSync(nsIURI* aURL, PRBool aAllowUnsafeRules,
PRBool aUseSystemPrincipal,
nsICSSStyleSheet** aSheet);
NS_IMETHOD LoadSheet(nsIURI* aURL,
nsIPrincipal* aOriginPrincipal,
const nsCString& aCharset,
nsICSSLoaderObserver* aObserver,
nsICSSStyleSheet** aSheet);
NS_IMETHOD LoadSheet(nsIURI* aURL,
nsIPrincipal* aOriginPrincipal,
const nsCString& aCharset,
nsICSSLoaderObserver* aObserver);
// stop loading all sheets
NS_IMETHOD Stop(void);
// stop loading one sheet
NS_IMETHOD StopLoadingSheet(nsIURI* aURL);
/**
* Is the loader enabled or not.
* When disabled, processing of new styles is disabled and an attempt
* to do so will fail with a return code of
* NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable
* currently loading styles or already processed styles.
*/
NS_IMETHOD GetEnabled(PRBool *aEnabled);
NS_IMETHOD SetEnabled(PRBool aEnabled);
NS_IMETHOD_(PRBool) HasPendingLoads();
NS_IMETHOD AddObserver(nsICSSLoaderObserver* aObserver);
NS_IMETHOD_(void) RemoveObserver(nsICSSLoaderObserver* aObserver);
// local helper methods (some are public for access from statics)
// IsAlternate can change our currently selected style set if none
// is selected and aHasAlternateRel is false.
PRBool IsAlternate(const nsAString& aTitle, PRBool aHasAlternateRel);
private:
// Note: null aSourcePrincipal indicates that the content policy and
// CheckLoadURI checks should be skipped.
nsresult CheckLoadAllowed(nsIPrincipal* aSourcePrincipal,
nsIURI* aTargetURI,
nsISupports* aContext);
// For inline style, the aURI param is null, but the aLinkingContent
// must be non-null then. The loader principal must never be null
// if aURI is not null.
nsresult CreateSheet(nsIURI* aURI,
nsIContent* aLinkingContent,
nsIPrincipal* aLoaderPrincipal,
PRBool aSyncLoad,
StyleSheetState& aSheetState,
nsICSSStyleSheet** aSheet);
// Pass in either a media string or the nsMediaList from the
// CSSParser. Don't pass both.
// If aIsAlternate is non-null, this method will set *aIsAlternate to
// correspond to the sheet's enabled state (which it will set no matter what)
nsresult PrepareSheet(nsICSSStyleSheet* aSheet,
const nsSubstring& aTitle,
const nsSubstring& aMediaString,
nsMediaList* aMediaList,
PRBool aHasAlternateRel = PR_FALSE,
PRBool *aIsAlternate = nsnull);
nsresult InsertSheetInDoc(nsICSSStyleSheet* aSheet,
nsIContent* aLinkingContent,
nsIDocument* aDocument);
nsresult InsertChildSheet(nsICSSStyleSheet* aSheet,
nsICSSStyleSheet* aParentSheet,
nsICSSImportRule* aParentRule);
nsresult InternalLoadNonDocumentSheet(nsIURI* aURL,
PRBool aAllowUnsafeRules,
PRBool aUseSystemPrincipal,
nsIPrincipal* aOriginPrincipal,
const nsCString& aCharset,
nsICSSStyleSheet** aSheet,
nsICSSLoaderObserver* aObserver);
// Post a load event for aObserver to be notified about aSheet. The
// notification will be sent with status NS_OK unless the load event is
// canceled at some point (in which case it will be sent with
// NS_BINDING_ABORTED). aWasAlternate indicates the state when the load was
// initiated, not the state at some later time. aURI should be the URI the
// sheet was loaded from (may be null for inline sheets).
nsresult PostLoadEvent(nsIURI* aURI,
nsICSSStyleSheet* aSheet,
nsICSSLoaderObserver* aObserver,
PRBool aWasAlternate);
// Start the loads of all the sheets in mPendingDatas
void StartAlternateLoads();
public:
// Handle an event posted by PostLoadEvent
void HandleLoadEvent(SheetLoadData* aEvent);
protected:
// Note: LoadSheet is responsible for releasing aLoadData and setting the
// sheet to complete on failure.
nsresult LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState);
friend class SheetLoadData;
// Protected functions and members are ones that SheetLoadData needs
// access to.
// Parse the stylesheet in aLoadData. The sheet data comes from aStream.
// Set aCompleted to true if the parse finished, false otherwise (e.g. if the
// sheet had an @import). If aCompleted is true when this returns, then
// ParseSheet also called SheetComplete on aLoadData
nsresult ParseSheet(nsIUnicharInputStream* aStream,
SheetLoadData* aLoadData,
PRBool& aCompleted);
// The load of the sheet in aLoadData is done, one way or another. Do final
// cleanup, including releasing aLoadData.
void SheetComplete(SheetLoadData* aLoadData, nsresult aStatus);
public:
typedef nsTArray<nsRefPtr<SheetLoadData> > LoadDataArray;
private:
// The guts of SheetComplete. This may be called recursively on parent datas
// or datas that had glommed on to a single load. The array is there so load
// datas whose observers need to be notified can be added to it.
void DoSheetComplete(SheetLoadData* aLoadData, nsresult aStatus,
LoadDataArray& aDatasToNotify);
static nsCOMArray<nsICSSParser>* gParsers; // array of idle CSS parsers
// the load data needs access to the document...
nsIDocument* mDocument; // the document we live for
#ifdef DEBUG
PRPackedBool mSyncCallback;
#endif
PRPackedBool mEnabled; // is enabled to load new styles
nsCompatibility mCompatMode;
nsString mPreferredSheet; // title of preferred sheet
nsInterfaceHashtable<nsURIAndPrincipalHashKey,
nsICSSStyleSheet> mCompleteSheets;
nsDataHashtable<nsURIAndPrincipalHashKey,
SheetLoadData*> mLoadingDatas; // weak refs
nsDataHashtable<nsURIAndPrincipalHashKey,
SheetLoadData*> mPendingDatas; // weak refs
// We're not likely to have many levels of @import... But likely to have
// some. Allocate some storage, what the hell.
nsAutoTArray<SheetLoadData*, 8> mParsingDatas;
// The array of posted stylesheet loaded events (SheetLoadDatas) we have.
// Note that these are rare.
LoadDataArray mPostedEvents;
// Number of datas still waiting to be notified on if we're notifying on a
// whole bunch at once (e.g. in one of the stop methods). This is used to
// make sure that HasPendingLoads() won't return false until we're notifying
// on the last data we're working with.
PRUint32 mDatasToNotifyOn;
// Our array of "global" observers
nsTObserverArray<nsCOMPtr<nsICSSLoaderObserver> > mObservers;
};
#endif // nsCSSLoader_h__

View File

@ -46,7 +46,7 @@
/* parsing of CSS stylesheets, based on a token stream from the CSS scanner */
#include "nsICSSParser.h"
#include "nsCSSParser.h"
#include "nsCSSProps.h"
#include "nsCSSKeywords.h"
#include "nsCSSScanner.h"
@ -153,82 +153,93 @@
//----------------------------------------------------------------------
namespace {
// Rule processing function
typedef void (* RuleAppendFunc) (nsICSSRule* aRule, void* aData);
static void AppendRuleToArray(nsICSSRule* aRule, void* aArray);
static void AppendRuleToSheet(nsICSSRule* aRule, void* aParser);
// Your basic top-down recursive descent style parser
class CSSParserImpl : public nsICSSParser {
// The exposed methods and members of this class are precisely those
// needed by nsCSSParser, far below.
class CSSParserImpl {
public:
CSSParserImpl();
virtual ~CSSParserImpl();
~CSSParserImpl();
NS_DECL_ISUPPORTS
nsresult SetStyleSheet(nsICSSStyleSheet* aSheet);
NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet);
NS_IMETHOD SetQuirkMode(PRBool aQuirkMode);
nsresult SetQuirkMode(PRBool aQuirkMode);
#ifdef MOZ_SVG
NS_IMETHOD SetSVGMode(PRBool aSVGMode);
nsresult SetSVGMode(PRBool aSVGMode);
#endif
NS_IMETHOD SetChildLoader(nsICSSLoader* aChildLoader);
nsresult SetChildLoader(nsICSSLoader* aChildLoader);
NS_IMETHOD Parse(nsIUnicharInputStream* aInput,
nsIURI* aSheetURI,
nsIURI* aBaseURI,
nsIPrincipal* aSheetPrincipal,
PRUint32 aLineNumber,
PRBool aAllowUnsafeRules);
// Clears everything set by the above Set*() functions.
void Reset();
NS_IMETHOD ParseStyleAttribute(const nsAString& aAttributeValue,
nsIURI* aDocURL,
nsIURI* aBaseURL,
nsIPrincipal* aNodePrincipal,
nsICSSStyleRule** aResult);
nsresult Parse(nsIUnicharInputStream* aInput,
nsIURI* aSheetURI,
nsIURI* aBaseURI,
nsIPrincipal* aSheetPrincipal,
PRUint32 aLineNumber,
PRBool aAllowUnsafeRules);
NS_IMETHOD ParseAndAppendDeclaration(const nsAString& aBuffer,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIPrincipal* aSheetPrincipal,
nsCSSDeclaration* aDeclaration,
PRBool aParseOnlyOneDecl,
PRBool* aChanged,
PRBool aClearOldDecl);
nsresult ParseStyleAttribute(const nsAString& aAttributeValue,
nsIURI* aDocURL,
nsIURI* aBaseURL,
nsIPrincipal* aNodePrincipal,
nsICSSStyleRule** aResult);
NS_IMETHOD ParseRule(const nsAString& aRule,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIPrincipal* aSheetPrincipal,
nsCOMArray<nsICSSRule>& aResult);
nsresult ParseAndAppendDeclaration(const nsAString& aBuffer,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIPrincipal* aSheetPrincipal,
nsCSSDeclaration* aDeclaration,
PRBool aParseOnlyOneDecl,
PRBool* aChanged,
PRBool aClearOldDecl);
NS_IMETHOD ParseProperty(const nsCSSProperty aPropID,
const nsAString& aPropValue,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIPrincipal* aSheetPrincipal,
nsCSSDeclaration* aDeclaration,
PRBool* aChanged);
nsresult ParseRule(const nsAString& aRule,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIPrincipal* aSheetPrincipal,
nsCOMArray<nsICSSRule>& aResult);
NS_IMETHOD ParseMediaList(const nsSubstring& aBuffer,
nsresult ParseProperty(const nsCSSProperty aPropID,
const nsAString& aPropValue,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIPrincipal* aSheetPrincipal,
nsCSSDeclaration* aDeclaration,
PRBool* aChanged);
nsresult ParseMediaList(const nsSubstring& aBuffer,
nsIURI* aURL, // for error reporting
PRUint32 aLineNumber, // for error reporting
nsMediaList* aMediaList,
PRBool aHTMLMode);
nsresult ParseColorString(const nsSubstring& aBuffer,
nsIURI* aURL, // for error reporting
PRUint32 aLineNumber, // for error reporting
nsMediaList* aMediaList,
PRBool aHTMLMode);
nscolor* aColor);
NS_IMETHOD ParseColorString(const nsSubstring& aBuffer,
nsIURI* aURL, // for error reporting
PRUint32 aLineNumber, // for error reporting
nscolor* aColor);
NS_IMETHOD ParseSelectorString(const nsSubstring& aSelectorString,
nsIURI* aURL, // for error reporting
PRUint32 aLineNumber, // for error reporting
nsCSSSelectorList **aSelectorList);
void AppendRule(nsICSSRule* aRule);
nsresult ParseSelectorString(const nsSubstring& aSelectorString,
nsIURI* aURL, // for error reporting
PRUint32 aLineNumber, // for error reporting
nsCSSSelectorList **aSelectorList);
protected:
class nsAutoParseCompoundProperty;
friend class nsAutoParseCompoundProperty;
void AppendRule(nsICSSRule* aRule);
friend void AppendRuleToSheet(nsICSSRule*, void*); // calls AppendRule
/**
* This helper class automatically calls SetParsingCompoundProperty in its
* constructor and takes care of resetting it to false in its destructor.
@ -596,10 +607,10 @@ protected:
nsCSSScanner mScanner;
// The URI to be used as a base for relative URIs.
nsCOMPtr<nsIURI> mBaseURL;
nsCOMPtr<nsIURI> mBaseURI;
// The URI to be used as an HTTP "Referer" and for error reporting.
nsCOMPtr<nsIURI> mSheetURL;
nsCOMPtr<nsIURI> mSheetURI;
// The principal of the sheet involved
nsCOMPtr<nsIPrincipal> mSheetPrincipal;
@ -646,6 +657,10 @@ protected:
// should set the low-level error to NS_ERROR_DOM_NAMESPACE_ERR
PRPackedBool mUnresolvablePrefixException : 1;
#ifdef DEBUG
PRPackedBool mScannerInited : 1;
#endif
// Stack of rule groups; used for @media and such.
nsCOMArray<nsICSSGroupRule> mGroupStack;
@ -659,9 +674,9 @@ protected:
// All data from successfully parsed properties are placed into |mData|.
nsCSSExpandedDataBlock mData;
#ifdef DEBUG
PRPackedBool mScannerInited;
#endif
public:
// Used from nsCSSParser constructors and destructors
CSSParserImpl* mNextFree;
};
static void AppendRuleToArray(nsICSSRule* aRule, void* aArray)
@ -675,18 +690,6 @@ static void AppendRuleToSheet(nsICSSRule* aRule, void* aParser)
parser->AppendRule(aRule);
}
nsresult
NS_NewCSSParser(nsICSSParser** aInstancePtrResult)
{
CSSParserImpl *it = new CSSParserImpl();
if (it == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
return it->QueryInterface(NS_GET_IID(nsICSSParser), (void **) aInstancePtrResult);
}
#ifdef CSS_REPORT_PARSE_ERRORS
#define REPORT_UNEXPECTED(msg_) \
@ -743,18 +746,17 @@ CSSParserImpl::CSSParserImpl()
#ifdef DEBUG
, mScannerInited(PR_FALSE)
#endif
, mNextFree(nsnull)
{
}
NS_IMPL_ISUPPORTS1(CSSParserImpl, nsICSSParser)
CSSParserImpl::~CSSParserImpl()
{
mData.AssertInitialState();
mTempData.AssertInitialState();
}
NS_IMETHODIMP
nsresult
CSSParserImpl::SetStyleSheet(nsICSSStyleSheet* aSheet)
{
if (aSheet != mSheet) {
@ -771,7 +773,7 @@ CSSParserImpl::SetStyleSheet(nsICSSStyleSheet* aSheet)
return NS_OK;
}
NS_IMETHODIMP
nsresult
CSSParserImpl::SetQuirkMode(PRBool aQuirkMode)
{
NS_ASSERTION(aQuirkMode == PR_TRUE || aQuirkMode == PR_FALSE, "bad PRBool value");
@ -780,7 +782,7 @@ CSSParserImpl::SetQuirkMode(PRBool aQuirkMode)
}
#ifdef MOZ_SVG
NS_IMETHODIMP
nsresult
CSSParserImpl::SetSVGMode(PRBool aSVGMode)
{
NS_ASSERTION(aSVGMode == PR_TRUE || aSVGMode == PR_FALSE,
@ -790,13 +792,23 @@ CSSParserImpl::SetSVGMode(PRBool aSVGMode)
}
#endif
NS_IMETHODIMP
nsresult
CSSParserImpl::SetChildLoader(nsICSSLoader* aChildLoader)
{
mChildLoader = aChildLoader; // not ref counted, it owns us
return NS_OK;
}
void
CSSParserImpl::Reset()
{
NS_ASSERTION(! mScannerInited, "resetting with scanner active");
SetStyleSheet(nsnull);
SetQuirkMode(PR_FALSE);
SetSVGMode(PR_FALSE);
SetChildLoader(nsnull);
}
void
CSSParserImpl::InitScanner(nsIUnicharInputStream* aInput, nsIURI* aSheetURI,
PRUint32 aLineNumber, nsIURI* aBaseURI,
@ -808,8 +820,8 @@ CSSParserImpl::InitScanner(nsIUnicharInputStream* aInput, nsIURI* aSheetURI,
#ifdef DEBUG
mScannerInited = PR_TRUE;
#endif
mBaseURL = aBaseURI;
mSheetURL = aSheetURI;
mBaseURI = aBaseURI;
mSheetURI = aSheetURI;
mSheetPrincipal = aSheetPrincipal;
mHavePushBack = PR_FALSE;
@ -829,8 +841,8 @@ CSSParserImpl::InitScanner(const nsSubstring& aString, nsIURI* aSheetURI,
#ifdef DEBUG
mScannerInited = PR_TRUE;
#endif
mBaseURL = aBaseURI;
mSheetURL = aSheetURI;
mBaseURI = aBaseURI;
mSheetURI = aSheetURI;
mSheetPrincipal = aSheetPrincipal;
mHavePushBack = PR_FALSE;
@ -843,13 +855,13 @@ CSSParserImpl::ReleaseScanner(void)
#ifdef DEBUG
mScannerInited = PR_FALSE;
#endif
mBaseURL = nsnull;
mSheetURL = nsnull;
mBaseURI = nsnull;
mSheetURI = nsnull;
mSheetPrincipal = nsnull;
}
NS_IMETHODIMP
nsresult
CSSParserImpl::Parse(nsIUnicharInputStream* aInput,
nsIURI* aSheetURI,
nsIURI* aBaseURI,
@ -859,8 +871,8 @@ CSSParserImpl::Parse(nsIUnicharInputStream* aInput,
{
NS_PRECONDITION(aSheetPrincipal, "Must have principal here!");
NS_ASSERTION(nsnull != aBaseURI, "need base URL");
NS_ASSERTION(nsnull != aSheetURI, "need sheet URL");
NS_ASSERTION(nsnull != aBaseURI, "need base URI");
NS_ASSERTION(nsnull != aSheetURI, "need sheet URI");
AssertInitialState();
NS_PRECONDITION(mSheet, "Must have sheet to parse into");
@ -949,20 +961,20 @@ NonMozillaVendorIdentifier(const nsAString& ident)
}
NS_IMETHODIMP
nsresult
CSSParserImpl::ParseStyleAttribute(const nsAString& aAttributeValue,
nsIURI* aDocURL,
nsIURI* aBaseURL,
nsIURI* aDocURI,
nsIURI* aBaseURI,
nsIPrincipal* aNodePrincipal,
nsICSSStyleRule** aResult)
{
NS_PRECONDITION(aNodePrincipal, "Must have principal here!");
AssertInitialState();
NS_ASSERTION(nsnull != aBaseURL, "need base URL");
NS_ASSERTION(nsnull != aBaseURI, "need base URI");
// XXX line number?
InitScanner(aAttributeValue, aDocURL, 0, aBaseURL, aNodePrincipal);
InitScanner(aAttributeValue, aDocURI, 0, aBaseURI, aNodePrincipal);
mSection = eCSSSection_General;
@ -1000,10 +1012,10 @@ CSSParserImpl::ParseStyleAttribute(const nsAString& aAttributeValue,
return NS_OK;
}
NS_IMETHODIMP
nsresult
CSSParserImpl::ParseAndAppendDeclaration(const nsAString& aBuffer,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIURI* aSheetURI,
nsIURI* aBaseURI,
nsIPrincipal* aSheetPrincipal,
nsCSSDeclaration* aDeclaration,
PRBool aParseOnlyOneDecl,
@ -1015,7 +1027,7 @@ CSSParserImpl::ParseAndAppendDeclaration(const nsAString& aBuffer,
*aChanged = PR_FALSE;
InitScanner(aBuffer, aSheetURL, 0, aBaseURL, aSheetPrincipal);
InitScanner(aBuffer, aSheetURI, 0, aBaseURI, aSheetPrincipal);
mSection = eCSSSection_General;
@ -1049,19 +1061,19 @@ CSSParserImpl::ParseAndAppendDeclaration(const nsAString& aBuffer,
return rv;
}
NS_IMETHODIMP
nsresult
CSSParserImpl::ParseRule(const nsAString& aRule,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIURI* aSheetURI,
nsIURI* aBaseURI,
nsIPrincipal* aSheetPrincipal,
nsCOMArray<nsICSSRule>& aResult)
{
NS_PRECONDITION(aSheetPrincipal, "Must have principal here!");
AssertInitialState();
NS_ASSERTION(nsnull != aBaseURL, "need base URL");
NS_ASSERTION(nsnull != aBaseURI, "need base URI");
InitScanner(aRule, aSheetURL, 0, aBaseURL, aSheetPrincipal);
InitScanner(aRule, aSheetURI, 0, aBaseURI, aSheetPrincipal);
mSection = eCSSSection_Charset; // callers are responsible for rejecting invalid rules.
@ -1083,11 +1095,11 @@ CSSParserImpl::ParseRule(const nsAString& aRule,
return NS_OK;
}
NS_IMETHODIMP
nsresult
CSSParserImpl::ParseProperty(const nsCSSProperty aPropID,
const nsAString& aPropValue,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIURI* aSheetURI,
nsIURI* aBaseURI,
nsIPrincipal* aSheetPrincipal,
nsCSSDeclaration* aDeclaration,
PRBool* aChanged)
@ -1095,11 +1107,11 @@ CSSParserImpl::ParseProperty(const nsCSSProperty aPropID,
NS_PRECONDITION(aSheetPrincipal, "Must have principal here!");
AssertInitialState();
NS_ASSERTION(nsnull != aBaseURL, "need base URL");
NS_ASSERTION(nsnull != aBaseURI, "need base URI");
NS_ASSERTION(nsnull != aDeclaration, "Need declaration to parse into!");
*aChanged = PR_FALSE;
InitScanner(aPropValue, aSheetURL, 0, aBaseURL, aSheetPrincipal);
InitScanner(aPropValue, aSheetURI, 0, aBaseURI, aSheetPrincipal);
mSection = eCSSSection_General;
@ -1167,9 +1179,9 @@ CSSParserImpl::ParseProperty(const nsCSSProperty aPropID,
return result;
}
NS_IMETHODIMP
nsresult
CSSParserImpl::ParseMediaList(const nsSubstring& aBuffer,
nsIURI* aURL, // for error reporting
nsIURI* aURI, // for error reporting
PRUint32 aLineNumber, // for error reporting
nsMediaList* aMediaList,
PRBool aHTMLMode)
@ -1178,8 +1190,8 @@ CSSParserImpl::ParseMediaList(const nsSubstring& aBuffer,
// has in case of parser error?
aMediaList->Clear();
// fake base URL since media lists don't have URLs in them
InitScanner(aBuffer, aURL, aLineNumber, aURL, nsnull);
// fake base URI since media lists don't have URIs in them
InitScanner(aBuffer, aURI, aLineNumber, aURI, nsnull);
AssertInitialState();
NS_ASSERTION(aHTMLMode == PR_TRUE || aHTMLMode == PR_FALSE,
@ -1213,14 +1225,14 @@ CSSParserImpl::ParseMediaList(const nsSubstring& aBuffer,
return rv;
}
NS_IMETHODIMP
nsresult
CSSParserImpl::ParseColorString(const nsSubstring& aBuffer,
nsIURI* aURL, // for error reporting
nsIURI* aURI, // for error reporting
PRUint32 aLineNumber, // for error reporting
nscolor* aColor)
{
AssertInitialState();
InitScanner(aBuffer, aURL, aLineNumber, aURL, nsnull);
InitScanner(aBuffer, aURI, aLineNumber, aURI, nsnull);
nsCSSValue value;
PRBool colorParsed = ParseColor(value);
@ -1262,13 +1274,13 @@ CSSParserImpl::ParseColorString(const nsSubstring& aBuffer,
return rv;
}
NS_IMETHODIMP
nsresult
CSSParserImpl::ParseSelectorString(const nsSubstring& aSelectorString,
nsIURI* aURL, // for error reporting
nsIURI* aURI, // for error reporting
PRUint32 aLineNumber, // for error reporting
nsCSSSelectorList **aSelectorList)
{
InitScanner(aSelectorString, aURL, aLineNumber, aURL, nsnull);
InitScanner(aSelectorString, aURI, aLineNumber, aURI, nsnull);
AssertInitialState();
@ -1916,8 +1928,8 @@ CSSParserImpl::ProcessImport(const nsString& aURLSpec,
// Diagnose bad URIs even if we don't have a child loader.
nsCOMPtr<nsIURI> url;
// Charset will be deduced from mBaseURL, which is more or less correct.
rv = NS_NewURI(getter_AddRefs(url), aURLSpec, nsnull, mBaseURL);
// Charset will be deduced from mBaseURI, which is more or less correct.
rv = NS_NewURI(getter_AddRefs(url), aURLSpec, nsnull, mBaseURI);
if (NS_FAILED(rv)) {
if (rv == NS_ERROR_MALFORMED_URI) {
@ -4778,7 +4790,7 @@ CSSParserImpl::SetValueToURL(nsCSSValue& aValue, const nsString& aURL)
// Translate url into an absolute url if the url is relative to the
// style sheet.
nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), aURL, nsnull, mBaseURL);
NS_NewURI(getter_AddRefs(uri), aURL, nsnull, mBaseURI);
nsStringBuffer* buffer = nsCSSValue::BufferFromString(aURL);
if (NS_UNLIKELY(!buffer)) {
@ -4786,7 +4798,7 @@ CSSParserImpl::SetValueToURL(nsCSSValue& aValue, const nsString& aURL)
return PR_FALSE;
}
nsCSSValue::URL *urlVal =
new nsCSSValue::URL(uri, buffer, mSheetURL, mSheetPrincipal);
new nsCSSValue::URL(uri, buffer, mSheetURI, mSheetPrincipal);
buffer->Release();
if (NS_UNLIKELY(!urlVal)) {
@ -9118,3 +9130,182 @@ CSSParserImpl::ParseMarker()
return PR_FALSE;
}
#endif
} // anonymous namespace
// Recycling of parser implementation objects
static CSSParserImpl* gFreeList = nsnull;
nsCSSParser::nsCSSParser(nsICSSLoader* aLoader,
nsICSSStyleSheet* aSheet)
{
CSSParserImpl *impl = gFreeList;
if (impl) {
gFreeList = impl->mNextFree;
impl->mNextFree = nsnull;
} else {
impl = new CSSParserImpl();
}
if (aLoader) {
impl->SetChildLoader(aLoader);
impl->SetQuirkMode(aLoader->GetCompatibilityMode() ==
eCompatibility_NavQuirks);
}
if (aSheet) {
impl->SetStyleSheet(aSheet);
}
mImpl = static_cast<void*>(impl);
}
nsCSSParser::~nsCSSParser()
{
CSSParserImpl *impl = static_cast<CSSParserImpl*>(mImpl);
impl->Reset();
impl->mNextFree = gFreeList;
gFreeList = impl;
}
/* static */ void
nsCSSParser::Shutdown()
{
CSSParserImpl *tofree = gFreeList;
CSSParserImpl *next;
while (tofree)
{
next = tofree->mNextFree;
delete tofree;
tofree = next;
}
}
// Wrapper methods
nsresult
nsCSSParser::SetStyleSheet(nsICSSStyleSheet* aSheet)
{
return static_cast<CSSParserImpl*>(mImpl)->
SetStyleSheet(aSheet);
}
nsresult
nsCSSParser::SetQuirkMode(PRBool aQuirkMode)
{
return static_cast<CSSParserImpl*>(mImpl)->
SetQuirkMode(aQuirkMode);
}
#ifdef MOZ_SVG
nsresult
nsCSSParser::SetSVGMode(PRBool aSVGMode)
{
return static_cast<CSSParserImpl*>(mImpl)->
SetSVGMode(aSVGMode);
}
#endif
nsresult
nsCSSParser::SetChildLoader(nsICSSLoader* aChildLoader)
{
return static_cast<CSSParserImpl*>(mImpl)->
SetChildLoader(aChildLoader);
}
nsresult
nsCSSParser::Parse(nsIUnicharInputStream* aInput,
nsIURI* aSheetURI,
nsIURI* aBaseURI,
nsIPrincipal* aSheetPrincipal,
PRUint32 aLineNumber,
PRBool aAllowUnsafeRules)
{
return static_cast<CSSParserImpl*>(mImpl)->
Parse(aInput, aSheetURI, aBaseURI, aSheetPrincipal, aLineNumber,
aAllowUnsafeRules);
}
nsresult
nsCSSParser::ParseStyleAttribute(const nsAString& aAttributeValue,
nsIURI* aDocURI,
nsIURI* aBaseURI,
nsIPrincipal* aNodePrincipal,
nsICSSStyleRule** aResult)
{
return static_cast<CSSParserImpl*>(mImpl)->
ParseStyleAttribute(aAttributeValue, aDocURI, aBaseURI,
aNodePrincipal, aResult);
}
nsresult
nsCSSParser::ParseAndAppendDeclaration(const nsAString& aBuffer,
nsIURI* aSheetURI,
nsIURI* aBaseURI,
nsIPrincipal* aSheetPrincipal,
nsCSSDeclaration* aDeclaration,
PRBool aParseOnlyOneDecl,
PRBool* aChanged,
PRBool aClearOldDecl)
{
return static_cast<CSSParserImpl*>(mImpl)->
ParseAndAppendDeclaration(aBuffer, aSheetURI, aBaseURI, aSheetPrincipal,
aDeclaration, aParseOnlyOneDecl, aChanged,
aClearOldDecl);
}
nsresult
nsCSSParser::ParseRule(const nsAString& aRule,
nsIURI* aSheetURI,
nsIURI* aBaseURI,
nsIPrincipal* aSheetPrincipal,
nsCOMArray<nsICSSRule>& aResult)
{
return static_cast<CSSParserImpl*>(mImpl)->
ParseRule(aRule, aSheetURI, aBaseURI, aSheetPrincipal, aResult);
}
nsresult
nsCSSParser::ParseProperty(const nsCSSProperty aPropID,
const nsAString& aPropValue,
nsIURI* aSheetURI,
nsIURI* aBaseURI,
nsIPrincipal* aSheetPrincipal,
nsCSSDeclaration* aDeclaration,
PRBool* aChanged)
{
return static_cast<CSSParserImpl*>(mImpl)->
ParseProperty(aPropID, aPropValue, aSheetURI, aBaseURI,
aSheetPrincipal, aDeclaration, aChanged);
}
nsresult
nsCSSParser::ParseMediaList(const nsSubstring& aBuffer,
nsIURI* aURI,
PRUint32 aLineNumber,
nsMediaList* aMediaList,
PRBool aHTMLMode)
{
return static_cast<CSSParserImpl*>(mImpl)->
ParseMediaList(aBuffer, aURI, aLineNumber, aMediaList, aHTMLMode);
}
nsresult
nsCSSParser::ParseColorString(const nsSubstring& aBuffer,
nsIURI* aURI,
PRUint32 aLineNumber,
nscolor* aColor)
{
return static_cast<CSSParserImpl*>(mImpl)->
ParseColorString(aBuffer, aURI, aLineNumber, aColor);
}
nsresult
nsCSSParser::ParseSelectorString(const nsSubstring& aSelectorString,
nsIURI* aURI,
PRUint32 aLineNumber,
nsCSSSelectorList** aSelectorList)
{
return static_cast<CSSParserImpl*>(mImpl)->
ParseSelectorString(aSelectorString, aURI, aLineNumber, aSelectorList);
}

View File

@ -37,16 +37,16 @@
/* parsing of CSS stylesheets, based on a token stream from the CSS scanner */
#ifndef nsICSSParser_h___
#define nsICSSParser_h___
#ifndef nsCSSParser_h___
#define nsCSSParser_h___
#include "nsISupports.h"
#include "nsAString.h"
#include "nsCSSProperty.h"
#include "nsColor.h"
#include "nsCOMArray.h"
class nsICSSStyleRule;
class nsICSSLoader;
class nsICSSStyleSheet;
class nsIUnicharInputStream;
class nsIURI;
@ -57,33 +57,42 @@ class nsMediaList;
class nsIPrincipal;
struct nsCSSSelectorList;
#define NS_ICSS_PARSER_IID \
{ 0xad4a3778, 0xdae0, 0x4640, \
{ 0xb2, 0x5a, 0x24, 0xff, 0x09, 0xc3, 0x70, 0xef } }
// Rule processing function
typedef void (* RuleAppendFunc) (nsICSSRule* aRule, void* aData);
// Interface to the css parser.
class nsICSSParser : public nsISupports {
class NS_STACK_CLASS nsCSSParser {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICSS_PARSER_IID)
NS_HIDDEN nsCSSParser(nsICSSLoader* aLoader = nsnull,
nsICSSStyleSheet* aSheet = nsnull);
NS_HIDDEN ~nsCSSParser();
static void Shutdown();
private:
// not to be implemented
nsCSSParser(nsCSSParser const&);
nsCSSParser& operator=(nsCSSParser const&);
public:
// If this is false, memory allocation failed in the constructor
// and all other methods will crash.
NS_HIDDEN operator bool() const
{ return !!mImpl; }
// Set a style sheet for the parser to fill in. The style sheet must
// implement the nsICSSStyleSheet interface. Null can be passed in to clear
// out an existing stylesheet reference.
NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet) = 0;
NS_HIDDEN_(nsresult) SetStyleSheet(nsICSSStyleSheet* aSheet);
// Set whether or not to emulate Nav quirks
NS_IMETHOD SetQuirkMode(PRBool aQuirkMode) = 0;
NS_HIDDEN_(nsresult) SetQuirkMode(PRBool aQuirkMode);
#ifdef MOZ_SVG
// Set whether or not we are in an SVG element
NS_IMETHOD SetSVGMode(PRBool aSVGMode) = 0;
NS_HIDDEN_(nsresult) SetSVGMode(PRBool aSVGMode);
#endif
// Set loader to use for child sheets
NS_IMETHOD SetChildLoader(nsICSSLoader* aChildLoader) = 0;
NS_HIDDEN_(nsresult) SetChildLoader(nsICSSLoader* aChildLoader);
/**
* Parse aInput into the stylesheet that was previously set by calling
@ -97,61 +106,62 @@ public:
* @param aBaseURI the URI to use for relative URI resolution
* @param aSheetPrincipal the principal of the stylesheet. This must match
* the principal of the sheet passed to SetStyleSheet.
* @param aLineNumber the line number of the first line of the sheet.
* @param aLineNumber the line number of the first line of the sheet.
* @param aAllowUnsafeRules see aEnableUnsafeRules in
* nsICSSLoader::LoadSheetSync
*/
NS_IMETHOD Parse(nsIUnicharInputStream* aInput,
nsIURI* aSheetURL,
nsIURI* aBaseURI,
nsIPrincipal* aSheetPrincipal,
PRUint32 aLineNumber,
PRBool aAllowUnsafeRules) = 0;
NS_HIDDEN_(nsresult) Parse(nsIUnicharInputStream* aInput,
nsIURI* aSheetURL,
nsIURI* aBaseURI,
nsIPrincipal* aSheetPrincipal,
PRUint32 aLineNumber,
PRBool aAllowUnsafeRules);
// Parse HTML style attribute or its equivalent in other markup
// languages. aBaseURL is the base url to use for relative links in
// the declaration.
NS_IMETHOD ParseStyleAttribute(const nsAString& aAttributeValue,
nsIURI* aDocURL,
nsIURI* aBaseURL,
nsIPrincipal* aNodePrincipal,
nsICSSStyleRule** aResult) = 0;
NS_HIDDEN_(nsresult) ParseStyleAttribute(const nsAString& aAttributeValue,
nsIURI* aDocURL,
nsIURI* aBaseURL,
nsIPrincipal* aNodePrincipal,
nsICSSStyleRule** aResult);
NS_IMETHOD ParseAndAppendDeclaration(const nsAString& aBuffer,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIPrincipal* aSheetPrincipal,
nsCSSDeclaration* aDeclaration,
PRBool aParseOnlyOneDecl,
PRBool* aChanged,
PRBool aClearOldDecl) = 0;
NS_HIDDEN_(nsresult) ParseAndAppendDeclaration(const nsAString& aBuffer,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIPrincipal* aSheetPrincipal,
nsCSSDeclaration* aDeclaration,
PRBool aParseOnlyOneDecl,
PRBool* aChanged,
PRBool aClearOldDecl);
NS_IMETHOD ParseRule(const nsAString& aRule,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIPrincipal* aSheetPrincipal,
nsCOMArray<nsICSSRule>& aResult) = 0;
NS_HIDDEN_(nsresult) ParseRule(const nsAString& aRule,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIPrincipal* aSheetPrincipal,
nsCOMArray<nsICSSRule>& aResult);
NS_IMETHOD ParseProperty(const nsCSSProperty aPropID,
const nsAString& aPropValue,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIPrincipal* aSheetPrincipal,
nsCSSDeclaration* aDeclaration,
PRBool* aChanged) = 0;
NS_HIDDEN_(nsresult) ParseProperty(const nsCSSProperty aPropID,
const nsAString& aPropValue,
nsIURI* aSheetURL,
nsIURI* aBaseURL,
nsIPrincipal* aSheetPrincipal,
nsCSSDeclaration* aDeclaration,
PRBool* aChanged);
/**
* Parse aBuffer into a media list |aMediaList|, which must be
* non-null, replacing its current contents. If aHTMLMode is true,
* parse according to HTML rules, with commas as the most important
* delimiter. Otherwise, parse according to CSS rules, with
* parentheses and strings more important than commas.
* parentheses and strings more important than commas. |aURL| and
* |aLineNumber| are used for error reporting.
*/
NS_IMETHOD ParseMediaList(const nsSubstring& aBuffer,
nsIURI* aURL, // for error reporting
PRUint32 aLineNumber, // for error reporting
nsMediaList* aMediaList,
PRBool aHTMLMode) = 0;
NS_HIDDEN_(nsresult) ParseMediaList(const nsSubstring& aBuffer,
nsIURI* aURL,
PRUint32 aLineNumber,
nsMediaList* aMediaList,
PRBool aHTMLMode);
/**
* Parse aBuffer into a nscolor |aColor|. The alpha component of the
@ -162,24 +172,25 @@ public:
* self-contained (i.e. doesn't reference any external style state,
* such as "initial" or "inherit").
*/
NS_IMETHOD ParseColorString(const nsSubstring& aBuffer,
nsIURI* aURL, // for error reporting
PRUint32 aLineNumber, // for error reporting
nscolor* aColor) = 0;
NS_HIDDEN_(nsresult) ParseColorString(const nsSubstring& aBuffer,
nsIURI* aURL,
PRUint32 aLineNumber,
nscolor* aColor);
/**
* Parse aBuffer into a selector list. On success, caller must
* delete *aSelectorList when done with it.
*/
NS_IMETHOD ParseSelectorString(const nsSubstring& aSelectorString,
nsIURI* aURL, // for error reporting
PRUint32 aLineNumber, // for error reporting
nsCSSSelectorList **aSelectorList) = 0;
NS_HIDDEN_(nsresult) ParseSelectorString(const nsSubstring& aSelectorString,
nsIURI* aURL,
PRUint32 aLineNumber,
nsCSSSelectorList** aSelectorList);
protected:
// This is a CSSParserImpl*, but if we expose that type name in this
// header, we can't put the type definition (in nsCSSParser.cpp) in
// the anonymous namespace.
void* mImpl;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsICSSParser, NS_ICSS_PARSER_IID)
nsresult
NS_NewCSSParser(nsICSSParser** aInstancePtrResult);
#endif /* nsICSSParser_h___ */
#endif /* nsCSSParser_h___ */

View File

@ -50,7 +50,6 @@
#include "nsICSSGroupRule.h"
#include "nsCSSDeclaration.h"
#include "nsICSSStyleSheet.h"
#include "nsICSSParser.h"
#include "nsICSSLoader.h"
#include "nsIURL.h"
#include "nsPresContext.h"
@ -913,8 +912,7 @@ public:
virtual nsresult GetCSSParsingEnvironment(nsIURI** aSheetURI,
nsIURI** aBaseURI,
nsIPrincipal** aSheetPrincipal,
nsICSSLoader** aCSSLoader,
nsICSSParser** aCSSParser);
nsICSSLoader** aCSSLoader);
virtual nsresult DeclarationChanged();
virtual nsIDocument* DocToUpdate();
@ -1018,19 +1016,17 @@ DOMCSSDeclarationImpl::GetCSSDeclaration(nsCSSDeclaration **aDecl,
* being initialized.
*/
nsresult
DOMCSSDeclarationImpl::GetCSSParsingEnvironment(nsIURI** aSheetURI,
DOMCSSDeclarationImpl::GetCSSParsingEnvironment(nsIURI** aSheetURI,
nsIURI** aBaseURI,
nsIPrincipal** aSheetPrincipal,
nsICSSLoader** aCSSLoader,
nsICSSParser** aCSSParser)
nsICSSLoader** aCSSLoader)
{
// null out the out params since some of them may not get initialized below
*aSheetURI = nsnull;
*aBaseURI = nsnull;
*aSheetPrincipal = nsnull;
*aCSSLoader = nsnull;
*aCSSParser = nsnull;
nsresult result;
nsCOMPtr<nsIStyleSheet> sheet;
if (mRule) {
mRule->GetStyleSheet(*getter_AddRefs(sheet));
@ -1050,14 +1046,9 @@ DOMCSSDeclarationImpl::GetCSSParsingEnvironment(nsIURI** aSheetURI,
}
}
}
// XXXldb Why bother if |mRule| is null?
if (*aCSSLoader) {
result = (*aCSSLoader)->GetParserFor(nsnull, aCSSParser);
} else {
result = NS_NewCSSParser(aCSSParser);
}
if (NS_SUCCEEDED(result) && !*aSheetPrincipal) {
nsresult result = NS_OK;
if (!*aSheetPrincipal) {
result = CallCreateInstance("@mozilla.org/nullprincipal;1",
aSheetPrincipal);
}

View File

@ -65,7 +65,7 @@
#include "nsIDOMMediaList.h"
#include "nsIDOMNode.h"
#include "nsDOMError.h"
#include "nsICSSParser.h"
#include "nsCSSParser.h"
#include "nsICSSLoader.h"
#include "nsICSSLoaderObserver.h"
#include "nsINameSpaceManager.h"
@ -555,9 +555,8 @@ nsMediaList::GetText(nsAString& aMediaText)
nsresult
nsMediaList::SetText(const nsAString& aMediaText)
{
nsCOMPtr<nsICSSParser> parser;
nsresult rv = NS_NewCSSParser(getter_AddRefs(parser));
NS_ENSURE_SUCCESS(rv, rv);
nsCSSParser parser;
NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
PRBool htmlMode = PR_FALSE;
nsCOMPtr<nsIDOMStyleSheet> domSheet =
@ -568,8 +567,8 @@ nsMediaList::SetText(const nsAString& aMediaText)
htmlMode = !!node;
}
return parser->ParseMediaList(nsString(aMediaText), nsnull, 0,
this, htmlMode);
return parser.ParseMediaList(nsString(aMediaText), nsnull, 0,
this, htmlMode);
}
PRBool
@ -1849,28 +1848,19 @@ nsCSSStyleSheet::InsertRuleInternal(const nsAString& aRule,
loader = mDocument->CSSLoader();
NS_ASSERTION(loader, "Document with no CSS loader!");
}
nsCOMPtr<nsICSSParser> css;
if (loader) {
result = loader->GetParserFor(this, getter_AddRefs(css));
}
else {
result = NS_NewCSSParser(getter_AddRefs(css));
if (css) {
css->SetStyleSheet(this);
}
}
if (NS_FAILED(result))
return result;
nsCSSParser css(loader, this);
if (!css)
return NS_ERROR_OUT_OF_MEMORY;
mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE);
nsCOMArray<nsICSSRule> rules;
result = css->ParseRule(aRule, mInner->mSheetURI, mInner->mBaseURI,
mInner->mPrincipal, rules);
result = css.ParseRule(aRule, mInner->mSheetURI, mInner->mBaseURI,
mInner->mPrincipal, rules);
if (NS_FAILED(result))
return result;
PRInt32 rulecount = rules.Count();
if (rulecount == 0) {
// Since we know aRule was not an empty string, just throw
@ -1969,10 +1959,6 @@ nsCSSStyleSheet::InsertRuleInternal(const nsAString& aRule,
}
}
if (loader) {
loader->RecycleParser(css);
}
*aReturn = aIndex;
return NS_OK;
}
@ -2085,17 +2071,10 @@ nsCSSStyleSheet::InsertRuleIntoGroup(const nsAString & aRule,
NS_ASSERTION(loader, "Document with no CSS loader!");
}
nsCOMPtr<nsICSSParser> css;
if (loader) {
result = loader->GetParserFor(this, getter_AddRefs(css));
nsCSSParser css(loader, this);
if (!css) {
return NS_ERROR_OUT_OF_MEMORY;
}
else {
result = NS_NewCSSParser(getter_AddRefs(css));
if (css) {
css->SetStyleSheet(this);
}
}
NS_ENSURE_SUCCESS(result, result);
// parse and grab the rule
mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE);
@ -2104,8 +2083,8 @@ nsCSSStyleSheet::InsertRuleIntoGroup(const nsAString & aRule,
NS_ENSURE_SUCCESS(result, result);
nsCOMArray<nsICSSRule> rules;
result = css->ParseRule(aRule, mInner->mSheetURI, mInner->mBaseURI,
mInner->mPrincipal, rules);
result = css.ParseRule(aRule, mInner->mSheetURI, mInner->mBaseURI,
mInner->mPrincipal, rules);
NS_ENSURE_SUCCESS(result, result);
PRInt32 rulecount = rules.Count();
@ -2137,10 +2116,6 @@ nsCSSStyleSheet::InsertRuleIntoGroup(const nsAString & aRule,
}
}
if (loader) {
loader->RecycleParser(css);
}
*_retval = aIndex;
return NS_OK;
}

View File

@ -43,7 +43,6 @@
#include "nsIDOMMutationEvent.h"
#include "nsICSSStyleRule.h"
#include "nsICSSLoader.h"
#include "nsICSSParser.h"
#include "nsIURI.h"
#include "nsINameSpaceManager.h"
#include "nsStyleConsts.h"
@ -183,8 +182,7 @@ nsresult
nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(nsIURI** aSheetURI,
nsIURI** aBaseURI,
nsIPrincipal** aSheetPrincipal,
nsICSSLoader** aCSSLoader,
nsICSSParser** aCSSParser)
nsICSSLoader** aCSSLoader)
{
NS_ASSERTION(mContent, "Something is severely broken -- there should be an nsIContent here!");
// null out the out params since some of them may not get initialized below
@ -192,7 +190,6 @@ nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(nsIURI** aSheetURI,
*aBaseURI = nsnull;
*aSheetPrincipal = nsnull;
*aCSSLoader = nsnull;
*aCSSParser = nsnull;
nsIDocument* doc = mContent->GetOwnerDoc();
if (!doc) {
@ -204,16 +201,7 @@ nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(nsIURI** aSheetURI,
nsCOMPtr<nsIURI> sheetURI = doc->GetDocumentURI();
NS_ADDREF(*aCSSLoader = doc->CSSLoader());
nsresult rv = NS_OK;
// Note: parsers coming from a CSSLoader for a document already have
// the right case-sensitivity, quirkiness, etc.
rv = (*aCSSLoader)->GetParserFor(nsnull, aCSSParser);
if (NS_FAILED(rv)) {
return rv;
}
baseURI.swap(*aBaseURI);
sheetURI.swap(*aSheetURI);
NS_ADDREF(*aSheetPrincipal = mContent->NodePrincipal());

View File

@ -47,7 +47,6 @@
#include "nsIContent.h"
class nsICSSLoader;
class nsICSSParser;
class nsDOMCSSAttributeDeclaration : public nsDOMCSSDeclaration,
public nsWrapperCache
@ -70,8 +69,7 @@ public:
virtual nsresult GetCSSParsingEnvironment(nsIURI** aSheetURI,
nsIURI** aBaseURI,
nsIPrincipal** aSheetPrincipal,
nsICSSLoader** aCSSLoader,
nsICSSParser** aCSSParser);
nsICSSLoader** aCSSLoader);
NS_IMETHOD GetParentRule(nsIDOMCSSRule **aParent);
virtual nsINode *GetParentObject()
@ -82,7 +80,7 @@ public:
protected:
virtual nsresult DeclarationChanged();
virtual nsIDocument* DocToUpdate();
nsCOMPtr<nsIContent> mContent;
#ifdef MOZ_SMIL

View File

@ -40,7 +40,7 @@
#include "nsDOMCSSDeclaration.h"
#include "nsIDOMCSSRule.h"
#include "nsICSSParser.h"
#include "nsCSSParser.h"
#include "nsICSSLoader.h"
#include "nsIStyleRule.h"
#include "nsCSSDeclaration.h"
@ -251,17 +251,15 @@ nsDOMCSSDeclaration::ParsePropertyValue(const nsCSSProperty aPropID,
if (!decl) {
return result;
}
nsCOMPtr<nsICSSLoader> cssLoader;
nsCOMPtr<nsICSSParser> cssParser;
nsCOMPtr<nsIURI> baseURI, sheetURI;
nsCOMPtr<nsIPrincipal> sheetPrincipal;
result = GetCSSParsingEnvironment(getter_AddRefs(sheetURI),
getter_AddRefs(baseURI),
getter_AddRefs(sheetPrincipal),
getter_AddRefs(cssLoader),
getter_AddRefs(cssParser));
getter_AddRefs(cssLoader));
if (NS_FAILED(result)) {
return result;
}
@ -273,17 +271,14 @@ nsDOMCSSDeclaration::ParsePropertyValue(const nsCSSProperty aPropID,
// rule (see stack in bug 209575).
mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), PR_TRUE);
nsCSSParser cssParser(cssLoader);
PRBool changed;
result = cssParser->ParseProperty(aPropID, aPropValue, sheetURI, baseURI,
sheetPrincipal, decl, &changed);
result = cssParser.ParseProperty(aPropID, aPropValue, sheetURI, baseURI,
sheetPrincipal, decl, &changed);
if (NS_SUCCEEDED(result) && changed) {
result = DeclarationChanged();
}
if (cssLoader) {
cssLoader->RecycleParser(cssParser);
}
return result;
}
@ -299,15 +294,13 @@ nsDOMCSSDeclaration::ParseDeclaration(const nsAString& aDecl,
}
nsCOMPtr<nsICSSLoader> cssLoader;
nsCOMPtr<nsICSSParser> cssParser;
nsCOMPtr<nsIURI> baseURI, sheetURI;
nsCOMPtr<nsIPrincipal> sheetPrincipal;
result = GetCSSParsingEnvironment(getter_AddRefs(sheetURI),
getter_AddRefs(baseURI),
getter_AddRefs(sheetPrincipal),
getter_AddRefs(cssLoader),
getter_AddRefs(cssParser));
getter_AddRefs(cssLoader));
if (NS_FAILED(result)) {
return result;
@ -320,21 +313,18 @@ nsDOMCSSDeclaration::ParseDeclaration(const nsAString& aDecl,
// rule (see stack in bug 209575).
mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), PR_TRUE);
nsCSSParser cssParser(cssLoader);
PRBool changed;
result = cssParser->ParseAndAppendDeclaration(aDecl, sheetURI, baseURI,
sheetPrincipal, decl,
aParseOnlyOneDecl,
&changed,
aClearOldDecl);
result = cssParser.ParseAndAppendDeclaration(aDecl, sheetURI, baseURI,
sheetPrincipal, decl,
aParseOnlyOneDecl,
&changed,
aClearOldDecl);
if (NS_SUCCEEDED(result) && changed) {
result = DeclarationChanged();
}
if (cssLoader) {
cssLoader->RecycleParser(cssParser);
}
return result;
}

View File

@ -46,7 +46,7 @@
#include "nsCOMPtr.h"
class nsCSSDeclaration;
class nsICSSParser;
class nsCSSParser;
class nsICSSLoader;
class nsIURI;
class nsIPrincipal;
@ -94,7 +94,7 @@ public:
const nsAString & value, const nsAString & priority);
NS_IMETHOD GetLength(PRUint32 *aLength);
NS_IMETHOD Item(PRUint32 index, nsAString & _retval);
NS_IMETHOD GetParentRule(nsIDOMCSSRule * *aParentRule) = 0;
NS_IMETHOD GetParentRule(nsIDOMCSSRule * *aParentRule) = 0;
protected:
// Always fills in the out parameter, even on failure, and if the out
@ -107,15 +107,14 @@ protected:
// calls to DeclarationChanged and the style rule mutation that leads
// to it.
virtual nsIDocument* DocToUpdate() = 0;
// This will only fail if it can't get a parser or a principal.
// This means it can return NS_OK without aURI or aCSSLoader being
// initialized.
virtual nsresult GetCSSParsingEnvironment(nsIURI** aSheetURI,
nsIURI** aBaseURI,
nsIPrincipal** aSheetPrincipal,
nsICSSLoader** aCSSLoader,
nsICSSParser** aCSSParser) = 0;
nsICSSLoader** aCSSLoader) = 0;
nsresult ParsePropertyValue(const nsCSSProperty aPropID,
const nsAString& aPropValue);
@ -125,8 +124,7 @@ protected:
// Prop-id based version of RemoveProperty. Note that this does not
// return the old value; it just does a straight removal.
nsresult RemoveProperty(const nsCSSProperty aPropID);
protected:
virtual ~nsDOMCSSDeclaration();
};

View File

@ -46,7 +46,7 @@
class nsIAtom;
class nsIURI;
class nsICSSParser;
class nsCSSParser;
class nsICSSStyleSheet;
class nsPresContext;
class nsIContent;
@ -58,10 +58,10 @@ class nsICSSImportRule;
class nsIPrincipal;
// IID for the nsICSSLoader interface
// 33c469dd-af03-4098-9984-b13cee34d86a
#define NS_ICSS_LOADER_IID \
{ 0x33c469dd, 0xaf03, 0x4098, \
{ 0x99, 0x84, 0xb1, 0x3c, 0xee, 0x34, 0xd8, 0x6a } }
// 4e12812e-490c-4cec-b0f4-75c8b79779ba
#define NS_ICSS_LOADER_IID \
{ 0x4e12812e, 0x490c, 0x4cec, \
{ 0xb0, 0xf4, 0x75, 0xc8, 0xb7, 0x97, 0x79, 0xba } }
typedef void (*nsCSSLoaderCallbackFunc)(nsICSSStyleSheet* aSheet, void *aData, PRBool aDidNotify);
@ -73,16 +73,12 @@ public:
NS_IMETHOD DropDocumentReference(void) = 0; // notification that doc is going away
NS_IMETHOD SetCompatibilityMode(nsCompatibility aCompatMode) = 0;
NS_IMETHOD_(nsCompatibility) GetCompatibilityMode() = 0;
NS_IMETHOD SetPreferredSheet(const nsAString& aTitle) = 0;
NS_IMETHOD GetPreferredSheet(nsAString& aTitle) = 0;
// Get/Recycle a CSS parser for general use
NS_IMETHOD GetParserFor(nsICSSStyleSheet* aSheet,
nsICSSParser** aParser) = 0;
NS_IMETHOD RecycleParser(nsICSSParser* aParser) = 0;
// XXXbz sort out what the deal is with events! When should they fire?
/**
* Load an inline style sheet. If a successful result is returned and
* *aCompleted is false, then aObserver is guaranteed to be notified

View File

@ -47,7 +47,7 @@
#include "nsStyleContext.h"
#include "nsStyleSet.h"
#include "nsComputedDOMStyle.h"
#include "nsICSSParser.h"
#include "nsCSSParser.h"
#include "nsICSSLoader.h"
#include "nsCSSDataBlock.h"
#include "nsCSSDeclaration.h"
@ -940,8 +940,8 @@ BuildStyleRule(nsCSSProperty aProperty,
PRBool changed; // ignored, but needed as outparam for ParseProperty
nsIDocument* doc = aTargetElement->GetOwnerDoc();
nsCOMPtr<nsIURI> baseURI = aTargetElement->GetBaseURI();
nsCOMPtr<nsICSSParser> parser;
nsCOMPtr<nsICSSStyleRule> styleRule;
nsCSSParser parser(doc->CSSLoader());
nsCSSProperty propertyToCheck = nsCSSProps::IsShorthand(aProperty) ?
nsCSSProps::SubpropertyEntryFor(aProperty)[0] : aProperty;
@ -951,12 +951,11 @@ BuildStyleRule(nsCSSProperty aProperty,
// and build a rule for the resulting declaration. If any of these steps
// fails, we bail out and delete the declaration.
if (!declaration->InitializeEmpty() ||
NS_FAILED(doc->CSSLoader()->GetParserFor(nsnull,
getter_AddRefs(parser))) ||
NS_FAILED(parser->ParseProperty(aProperty, aSpecifiedValue,
doc->GetDocumentURI(), baseURI,
aTargetElement->NodePrincipal(),
declaration, &changed)) ||
!parser ||
NS_FAILED(parser.ParseProperty(aProperty, aSpecifiedValue,
doc->GetDocumentURI(), baseURI,
aTargetElement->NodePrincipal(),
declaration, &changed)) ||
// check whether property parsed without CSS parsing errors
!declaration->HasNonImportantValueFor(propertyToCheck) ||
NS_FAILED(NS_NewCSSStyleRule(getter_AddRefs(styleRule), nsnull,