nsresult nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument *aOldDocument, nsICSSLoaderObserver* aObserver, bool* aWillNotify, bool* aIsAlternate, bool aForceUpdate) { *aWillNotify = false; if (mStyleSheet && aOldDocument) { // We're removing the link element from the document, unload the // stylesheet. We want to do this even if updates are disabled, since // otherwise a sheet with a stale linking element pointer will be hanging // around -- not good! aOldDocument->BeginUpdate(UPDATE_STYLE); aOldDocument->RemoveStyleSheet(mStyleSheet); aOldDocument->EndUpdate(UPDATE_STYLE); nsStyleLinkElement::SetStyleSheet(nullptr); } nsCOMPtr<nsIContent> thisContent; QueryInterface(NS_GET_IID(nsIContent), getter_AddRefs(thisContent)); NS_ENSURE_TRUE(thisContent, NS_ERROR_FAILURE); // When static documents are created, stylesheets are cloned manually. if (mDontLoadStyle || !mUpdatesEnabled || thisContent->OwnerDoc()->IsStaticDocument()) { return NS_OK; } nsCOMPtr<nsIDocument> doc = thisContent->GetDocument(); if (!doc || !doc->CSSLoader()->GetEnabled()) { return NS_OK; } bool isInline; nsCOMPtr<nsIURI> uri = GetStyleSheetURL(&isInline); if (!aForceUpdate && mStyleSheet && !isInline && uri) { nsIURI* oldURI = mStyleSheet->GetSheetURI(); if (oldURI) { bool equal; nsresult rv = oldURI->Equals(uri, &equal); if (NS_SUCCEEDED(rv) && equal) { return NS_OK; // We already loaded this stylesheet } } } if (mStyleSheet) { doc->BeginUpdate(UPDATE_STYLE); doc->RemoveStyleSheet(mStyleSheet); doc->EndUpdate(UPDATE_STYLE); nsStyleLinkElement::SetStyleSheet(nullptr); } if (!uri && !isInline) { return NS_OK; // If href is empty and this is not inline style then just bail } nsAutoString title, type, media; bool isAlternate; GetStyleSheetInfo(title, type, media, &isAlternate); if (!type.LowerCaseEqualsLiteral("text/css")) { return NS_OK; } bool doneLoading = false; nsresult rv = NS_OK; if (isInline) { nsAutoString text; nsContentUtils::GetNodeTextContent(thisContent, false, text); // Parse the style sheet. rv = doc->CSSLoader()-> LoadInlineStyle(thisContent, text, mLineNumber, title, media, aObserver, &doneLoading, &isAlternate); } else { // XXXbz clone the URI here to work around content policies modifying URIs. nsCOMPtr<nsIURI> clonedURI; uri->Clone(getter_AddRefs(clonedURI)); NS_ENSURE_TRUE(clonedURI, NS_ERROR_OUT_OF_MEMORY); rv = doc->CSSLoader()-> LoadStyleLink(thisContent, clonedURI, title, media, isAlternate, GetCORSMode(), aObserver, &isAlternate); if (NS_FAILED(rv)) { // Don't propagate LoadStyleLink() errors further than this, since some // consumers (e.g. nsXMLContentSink) will completely abort on innocuous // things like a stylesheet load being blocked by the security system. doneLoading = true; isAlternate = false; rv = NS_OK; } } NS_ENSURE_SUCCESS(rv, rv); *aWillNotify = !doneLoading; *aIsAlternate = isAlternate; return NS_OK; }
NS_IMETHODIMP nsStyleLinkElement::UpdateStyleSheet(nsIDocument *aOldDocument, nsICSSLoaderObserver* aObserver) { if (mStyleSheet && aOldDocument) { // We're removing the link element from the document, unload the // stylesheet. We want to do this even if updates are disabled, since // otherwise a sheet with a stale linking element pointer will be hanging // around -- not good! aOldDocument->BeginUpdate(UPDATE_STYLE); aOldDocument->RemoveStyleSheet(mStyleSheet); aOldDocument->EndUpdate(UPDATE_STYLE); nsStyleLinkElement::SetStyleSheet(nsnull); } if (mDontLoadStyle || !mUpdatesEnabled) { return NS_OK; } // Keep a strong ref to the parser so it's still around when we pass it // to the CSS loader. Release strong ref in mParser so we don't hang on // to the parser once we start the load or if we fail to load the // stylesheet. nsCOMPtr<nsIParser> parser = mParser; mParser = nsnull; nsCOMPtr<nsIContent> thisContent; QueryInterface(NS_GET_IID(nsIContent), getter_AddRefs(thisContent)); NS_ENSURE_TRUE(thisContent, NS_ERROR_FAILURE); nsCOMPtr<nsIDocument> doc = thisContent->GetDocument(); if (!doc) { return NS_OK; } nsCOMPtr<nsIURI> uri; PRBool isInline; GetStyleSheetURL(&isInline, getter_AddRefs(uri)); if (mStyleSheet && !isInline && uri) { nsCOMPtr<nsIURI> oldURI; mStyleSheet->GetSheetURI(getter_AddRefs(oldURI)); if (oldURI) { PRBool equal; nsresult rv = oldURI->Equals(uri, &equal); if (NS_SUCCEEDED(rv) && equal) { return NS_OK; // We already loaded this stylesheet } } } if (mStyleSheet) { doc->BeginUpdate(UPDATE_STYLE); doc->RemoveStyleSheet(mStyleSheet); doc->EndUpdate(UPDATE_STYLE); nsStyleLinkElement::SetStyleSheet(nsnull); } if (!uri && !isInline) { return NS_OK; // If href is empty and this is not inline style then just bail } nsAutoString title, type, media; PRBool isAlternate; GetStyleSheetInfo(title, type, media, &isAlternate); if (!type.LowerCaseEqualsLiteral("text/css")) { return NS_OK; } PRBool blockParser = kBlockByDefault; if (isAlternate) { blockParser = PR_FALSE; } /* NOTE: no longer honoring the important keyword to indicate blocking as it is proprietary and unnecessary since all non-alternate will block the parser now -mja if (-1 != linkTypes.IndexOf("important")) { blockParser = PR_TRUE; } */ if (!isAlternate && !title.IsEmpty()) { // possibly preferred sheet nsAutoString prefStyle; doc->GetHeaderData(nsHTMLAtoms::headerDefaultStyle, prefStyle); if (prefStyle.IsEmpty()) { doc->SetHeaderData(nsHTMLAtoms::headerDefaultStyle, title); } } PRBool doneLoading; nsresult rv = NS_OK; if (isInline) { PRUint32 count = thisContent->GetChildCount(); nsAutoString content; PRUint32 i; for (i = 0; i < count; ++i) { nsIContent *node = thisContent->GetChildAt(i); nsCOMPtr<nsIDOMText> tc = do_QueryInterface(node); // Ignore nodes that are not DOMText. if (!tc) { nsCOMPtr<nsIDOMComment> comment = do_QueryInterface(node); if (comment) // Skip a comment continue; break; } nsAutoString tcString; tc->GetData(tcString); content.Append(tcString); } // Use of the stream will be done before parsing returns. So it will go // out of scope before |content| does. nsCOMPtr<nsIUnicharInputStream> uin; rv = NS_NewStringUnicharInputStream(getter_AddRefs(uin), &content, PR_FALSE); if (NS_FAILED(rv)) { return rv; } // Now that we have a url and a unicode input stream, parse the // style sheet. rv = doc->CSSLoader()-> LoadInlineStyle(thisContent, uin, mLineNumber, title, media, ((blockParser) ? parser.get() : nsnull), doneLoading, aObserver); } else { rv = doc->CSSLoader()-> LoadStyleLink(thisContent, uri, title, media, ((blockParser) ? parser.get() : nsnull), doneLoading, aObserver); } if (NS_SUCCEEDED(rv) && blockParser && !doneLoading) { rv = NS_ERROR_HTMLPARSER_BLOCK; } return rv; }
nsresult nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument *aOldDocument, nsICSSLoaderObserver* aObserver, PRBool* aWillNotify, PRBool* aIsAlternate, PRBool aForceUpdate) { *aWillNotify = PR_FALSE; if (mStyleSheet && aOldDocument) { // We're removing the link element from the document, unload the // stylesheet. We want to do this even if updates are disabled, since // otherwise a sheet with a stale linking element pointer will be hanging // around -- not good! aOldDocument->BeginUpdate(UPDATE_STYLE); aOldDocument->RemoveStyleSheet(mStyleSheet); aOldDocument->EndUpdate(UPDATE_STYLE); mStyleSheet = nsnull; } if (mDontLoadStyle || !mUpdatesEnabled) { return NS_OK; } nsCOMPtr<nsIContent> thisContent; QueryInterface(NS_GET_IID(nsIContent), getter_AddRefs(thisContent)); NS_ENSURE_TRUE(thisContent, NS_ERROR_FAILURE); nsCOMPtr<nsIDocument> doc = thisContent->GetDocument(); if (!doc) { return NS_OK; } PRBool enabled = PR_FALSE; doc->CSSLoader()->GetEnabled(&enabled); if (!enabled) { return NS_OK; } nsCOMPtr<nsIURI> uri; PRBool isInline; GetStyleSheetURL(&isInline, getter_AddRefs(uri)); if (!aForceUpdate && mStyleSheet && !isInline && uri) { nsCOMPtr<nsIURI> oldURI; mStyleSheet->GetSheetURI(getter_AddRefs(oldURI)); if (oldURI) { PRBool equal; nsresult rv = oldURI->Equals(uri, &equal); if (NS_SUCCEEDED(rv) && equal) { return NS_OK; // We already loaded this stylesheet } } } if (mStyleSheet) { doc->BeginUpdate(UPDATE_STYLE); doc->RemoveStyleSheet(mStyleSheet); doc->EndUpdate(UPDATE_STYLE); mStyleSheet = nsnull; } if (!uri && !isInline) { return NS_OK; // If href is empty and this is not inline style then just bail } nsAutoString title, type, media; PRBool isAlternate; GetStyleSheetInfo(title, type, media, &isAlternate); if (!type.LowerCaseEqualsLiteral("text/css")) { return NS_OK; } PRBool doneLoading = PR_FALSE; nsresult rv = NS_OK; if (isInline) { nsAutoString content; nsContentUtils::GetNodeTextContent(thisContent, PR_FALSE, content); nsCOMPtr<nsIUnicharInputStream> uin; rv = nsSimpleUnicharStreamFactory::GetInstance()-> CreateInstanceFromString(content, getter_AddRefs(uin)); if (NS_FAILED(rv)) { return rv; } // Now that we have a url and a unicode input stream, parse the // style sheet. rv = doc->CSSLoader()-> LoadInlineStyle(thisContent, uin, mLineNumber, title, media, aObserver, &doneLoading, &isAlternate); } else { rv = doc->CSSLoader()-> LoadStyleLink(thisContent, uri, title, media, isAlternate, aObserver, &isAlternate); if (rv == NS_ERROR_FILE_NOT_FOUND) { doneLoading = PR_TRUE; rv = NS_OK; } } NS_ENSURE_SUCCESS(rv, rv); *aWillNotify = !doneLoading; *aIsAlternate = isAlternate; return NS_OK; }