Bug 454578. Load the quirk stylesheet separately from the general UA stylesheet, so it can be sensibly enabled/disabled in style sets. r+sr=dbaron

This commit is contained in:
Boris Zbarsky 2008-11-02 21:29:51 -05:00
Родитель 06998b3fc5
Коммит 9cd26aa818
13 изменённых файлов: 86 добавлений и 172 удалений

Просмотреть файл

@ -321,7 +321,6 @@ public:
NS_DECL_NSICONTENTVIEWER
// nsIDocumentViewer interface...
NS_IMETHOD SetUAStyleSheet(nsIStyleSheet* aUAStyleSheet);
NS_IMETHOD GetDocument(nsIDocument** aResult);
NS_IMETHOD GetPresShell(nsIPresShell** aResult);
NS_IMETHOD GetPresContext(nsPresContext** aResult);
@ -425,8 +424,6 @@ protected:
nsCOMPtr<nsPresContext> mPresContext;
nsCOMPtr<nsIPresShell> mPresShell;
nsCOMPtr<nsIStyleSheet> mUAStyleSheet;
nsCOMPtr<nsISelectionListener> mSelectionListener;
nsCOMPtr<nsIDOMFocusListener> mFocusListener;
@ -1659,19 +1656,6 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument)
return rv;
}
NS_IMETHODIMP
DocumentViewerImpl::SetUAStyleSheet(nsIStyleSheet* aUAStyleSheet)
{
NS_ASSERTION(aUAStyleSheet, "unexpected null pointer");
nsCOMPtr<nsICSSStyleSheet> sheet(do_QueryInterface(aUAStyleSheet));
if (sheet) {
nsCOMPtr<nsICSSStyleSheet> newSheet;
sheet->Clone(nsnull, nsnull, nsnull, nsnull, getter_AddRefs(newSheet));
mUAStyleSheet = newSheet;
}
return NS_OK;
}
NS_IMETHODIMP
DocumentViewerImpl::GetDocument(nsIDocument** aResult)
{
@ -2091,10 +2075,6 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument,
// this should eventually get expanded to allow for creating
// different sets for different media
if (!mUAStyleSheet) {
NS_WARNING("unable to load UA style sheet");
}
nsStyleSet *styleSet = new nsStyleSet();
if (!styleSet) {
return NS_ERROR_OUT_OF_MEMORY;
@ -2177,9 +2157,24 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument,
styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, sheet);
}
if (mUAStyleSheet) {
styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, mUAStyleSheet);
// Make sure to clone the quirk sheet so that it can be usefully
// enabled/disabled as needed.
nsCOMPtr<nsICSSStyleSheet> quirkClone;
if (!nsLayoutStylesheetCache::UASheet() ||
!nsLayoutStylesheetCache::QuirkSheet() ||
NS_FAILED(nsLayoutStylesheetCache::QuirkSheet()->
Clone(nsnull, nsnull, nsnull, nsnull,
getter_AddRefs(quirkClone))) ||
!sheet) {
delete styleSet;
return NS_ERROR_OUT_OF_MEMORY;
}
// quirk.css needs to come after the regular UA sheet (or more precisely,
// after the html.css and so forth that the UA sheet imports).
styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, quirkClone);
styleSet->SetQuirkStyleSheet(quirkClone);
styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet,
nsLayoutStylesheetCache::UASheet());
nsCOMPtr<nsIStyleSheetService> dummy =
do_GetService(NS_STYLESHEETSERVICE_CONTRACTID);

Просмотреть файл

@ -48,7 +48,7 @@ class nsIPresShell;
class nsIStyleSheet;
#define NS_IDOCUMENT_VIEWER_IID \
{ 0x41796e63, 0xbd1f, 0x401d,{0xb6, 0x63, 0x5b, 0x86, 0xa9, 0x70, 0x72, 0x31}}
{ 0xf81fc126, 0x6693, 0x4bc5,{0xa7, 0xe9, 0xfc, 0xb0, 0x76, 0xd9, 0x06, 0x6d} }
/**
* A document viewer is a kind of content viewer that uses NGLayout
@ -59,8 +59,6 @@ class nsIDocumentViewer : public nsIContentViewer
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_VIEWER_IID)
NS_IMETHOD SetUAStyleSheet(nsIStyleSheet* aUAStyleSheet) = 0;
NS_IMETHOD GetDocument(nsIDocument** aResult) = 0;
NS_IMETHOD GetPresShell(nsIPresShell** aResult) = 0;

Просмотреть файл

@ -69,9 +69,6 @@
static NS_DEFINE_CID(kPluginManagerCID, NS_PLUGINMANAGER_CID);
static NS_DEFINE_CID(kPluginDocumentCID, NS_PLUGINDOCUMENT_CID);
// URL for the "user agent" style sheet
#define UA_CSS_URL "resource://gre/res/ua.css"
// Factory code for creating variations on html documents
#undef NOISY_REGISTRY
@ -131,8 +128,6 @@ static const char* const gXULTypes[] = {
0
};
nsICSSStyleSheet* nsContentDLF::gUAStyleSheet;
nsresult
NS_NewContentDocumentLoaderFactory(nsIDocumentLoaderFactory** aResult)
{
@ -169,8 +164,6 @@ nsContentDLF::CreateInstance(const char* aCommand,
nsIStreamListener** aDocListener,
nsIContentViewer** aDocViewer)
{
EnsureUAStyleSheet();
// Are we viewing source?
#ifdef MOZ_VIEW_SOURCE
nsCOMPtr<nsIViewSourceChannel> viewSourceChannel = do_QueryInterface(aChannel);
@ -314,16 +307,12 @@ nsContentDLF::CreateInstanceForDocument(nsISupports* aContainer,
{
nsresult rv = NS_ERROR_FAILURE;
EnsureUAStyleSheet();
do {
nsCOMPtr<nsIDocumentViewer> docv;
rv = NS_NewDocumentViewer(getter_AddRefs(docv));
if (NS_FAILED(rv))
break;
docv->SetUAStyleSheet(static_cast<nsIStyleSheet*>(gUAStyleSheet));
// Bind the document to the Content Viewer
nsIContentViewer* cv = static_cast<nsIContentViewer*>(docv.get());
rv = cv->LoadStart(aDocument);
@ -439,7 +428,6 @@ nsContentDLF::CreateDocument(const char* aCommand,
rv = NS_NewDocumentViewer(getter_AddRefs(docv));
if (NS_FAILED(rv))
break;
docv->SetUAStyleSheet(gUAStyleSheet);
doc->SetContainer(aContainer);
@ -477,9 +465,6 @@ nsContentDLF::CreateXULDocument(const char* aCommand,
rv = NS_NewDocumentViewer(getter_AddRefs(docv));
if (NS_FAILED(rv)) return rv;
// Load the UA style sheet if we haven't already done that
docv->SetUAStyleSheet(gUAStyleSheet);
nsCOMPtr<nsIURI> aURL;
rv = aChannel->GetURI(getter_AddRefs(aURL));
if (NS_FAILED(rv)) return rv;
@ -618,30 +603,3 @@ nsContentDLF::UnregisterDocumentFactories(nsIComponentManager* aCompMgr,
return rv;
}
/* static */ nsresult
nsContentDLF::EnsureUAStyleSheet()
{
if (gUAStyleSheet)
return NS_OK;
// Load the UA style sheet
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING(UA_CSS_URL));
if (NS_FAILED(rv)) {
#ifdef DEBUG
printf("*** open of %s failed: error=%x\n", UA_CSS_URL, rv);
#endif
return rv;
}
nsCOMPtr<nsICSSLoader> cssLoader;
NS_NewCSSLoader(getter_AddRefs(cssLoader));
if (!cssLoader)
return NS_ERROR_OUT_OF_MEMORY;
rv = cssLoader->LoadSheetSync(uri, PR_TRUE, &gUAStyleSheet);
#ifdef DEBUG
if (NS_FAILED(rv))
printf("*** open of %s failed: error=%x\n", UA_CSS_URL, rv);
#endif
return rv;
}

Просмотреть файл

@ -81,8 +81,6 @@ public:
nsIStreamListener** aDocListener,
nsIContentViewer** aDocViewer);
static nsICSSStyleSheet* gUAStyleSheet;
#ifdef MOZ_SVG
static NS_IMETHODIMP RegisterSVG();
static NS_IMETHODIMP UnregisterSVG();

Просмотреть файл

@ -312,7 +312,6 @@ nsLayoutStatics::Shutdown()
nsCSSScanner::ReleaseGlobals();
NS_IF_RELEASE(nsContentDLF::gUAStyleSheet);
NS_IF_RELEASE(nsRuleNode::gLangService);
nsStyledElement::Shutdown();
@ -323,7 +322,6 @@ nsLayoutStatics::Shutdown()
nsNodeInfo::ClearCache();
nsLayoutStylesheetCache::Shutdown();
NS_NameSpaceManagerShutdown();
nsStyleSet::FreeGlobals();
nsJSRuntime::Shutdown();
nsGlobalWindow::ShutDown();

Просмотреть файл

@ -1280,46 +1280,6 @@ nsCSSStyleSheet::GetOwnerRule(nsICSSImportRule** aOwnerRule)
return NS_OK;
}
NS_IMETHODIMP
nsCSSStyleSheet::ContainsStyleSheet(nsIURI* aURL, PRBool& aContains, nsIStyleSheet** aTheChild /*=nsnull*/)
{
NS_PRECONDITION(nsnull != aURL, "null arg");
if (!mInner->mSheetURI) {
// We're not yet far enough along in our load to know what our URL is (we
// may still get redirected and such). Assert (caller should really not be
// calling this on us at this stage) and return.
NS_ERROR("ContainsStyleSheet called on a sheet that's still loading");
aContains = PR_FALSE;
return NS_OK;
}
// first check ourself out
nsresult rv = mInner->mSheetURI->Equals(aURL, &aContains);
if (NS_FAILED(rv)) aContains = PR_FALSE;
if (aContains) {
// if we found it and the out-param is there, set it and addref
if (aTheChild) {
rv = CallQueryInterface(this, aTheChild);
}
} else {
// now check the chil'ins out (recursively)
for (nsCSSStyleSheet* child = mInner->mFirstChild;
child;
child = child->mNext) {
child->ContainsStyleSheet(aURL, aContains, aTheChild);
if (aContains) {
break;
}
}
}
// NOTE: if there are errors in the above we are handling them locally
// and not promoting them to the caller
return NS_OK;
}
NS_IMETHODIMP
nsCSSStyleSheet::AppendStyleSheet(nsICSSStyleSheet* aSheet)
{

Просмотреть файл

@ -133,8 +133,6 @@ public:
#endif
// nsICSSStyleSheet interface
NS_IMETHOD ContainsStyleSheet(nsIURI* aURL, PRBool& aContains,
nsIStyleSheet** aTheChild=nsnull);
NS_IMETHOD AppendStyleSheet(nsICSSStyleSheet* aSheet);
NS_IMETHOD InsertStyleSheetAt(nsICSSStyleSheet* aSheet, PRInt32 aIndex);
NS_IMETHOD PrependStyleRule(nsICSSRule* aRule);

Просмотреть файл

@ -53,17 +53,15 @@ class nsICSSImportRule;
class nsIPrincipal;
// IID for the nsICSSStyleSheet interface
// 363c1c5f-81ec-4d83-ad8a-b48d48f1398d
// ee0270c7-5581-4165-92a5-a83ff691f60d
#define NS_ICSS_STYLE_SHEET_IID \
{ 0x363c1c5f, 0x81ec, 0x4d83, \
{ 0xad, 0x8a, 0xb4, 0x8d, 0x48, 0xf1, 0x39, 0x8d } }
{ 0xee0270c7, 0x5581, 0x4165, \
{ 0x92, 0xa5, 0xa8, 0x3f, 0xf6, 0x91, 0xf6, 0x0d } }
class nsICSSStyleSheet : public nsIStyleSheet {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICSS_STYLE_SHEET_IID)
NS_IMETHOD ContainsStyleSheet(nsIURI* aURL, PRBool& aContains, nsIStyleSheet** aTheChild=nsnull) = 0;
NS_IMETHOD AppendStyleSheet(nsICSSStyleSheet* aSheet) = 0;
NS_IMETHOD InsertStyleSheetAt(nsICSSStyleSheet* aSheet, PRInt32 aIndex) = 0;

Просмотреть файл

@ -133,6 +133,26 @@ nsLayoutStylesheetCache::UserChromeSheet()
return gStyleCache->mUserChromeSheet;
}
nsICSSStyleSheet*
nsLayoutStylesheetCache::UASheet()
{
EnsureGlobal();
if (!gStyleCache)
return nsnull;
return gStyleCache->mUASheet;
}
nsICSSStyleSheet*
nsLayoutStylesheetCache::QuirkSheet()
{
EnsureGlobal();
if (!gStyleCache)
return nsnull;
return gStyleCache->mQuirkSheet;
}
void
nsLayoutStylesheetCache::Shutdown()
{
@ -154,6 +174,21 @@ nsLayoutStylesheetCache::nsLayoutStylesheetCache()
}
InitFromProfile();
// And make sure that we load our UA sheets. No need to do this
// per-profile, since they're profile-invariant.
nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), "resource://gre/res/ua.css");
if (uri) {
LoadSheet(uri, mUASheet, PR_TRUE);
}
NS_ASSERTION(mUASheet, "Could not load ua.css");
NS_NewURI(getter_AddRefs(uri), "resource://gre/res/quirk.css");
if (uri) {
LoadSheet(uri, mQuirkSheet, PR_TRUE);
}
NS_ASSERTION(mQuirkSheet, "Could not load quirk.css");
}
nsLayoutStylesheetCache::~nsLayoutStylesheetCache()

Просмотреть файл

@ -55,6 +55,8 @@ class nsLayoutStylesheetCache
static nsICSSStyleSheet* FormsSheet();
static nsICSSStyleSheet* UserContentSheet();
static nsICSSStyleSheet* UserChromeSheet();
static nsICSSStyleSheet* UASheet();
static nsICSSStyleSheet* QuirkSheet();
static void Shutdown();
@ -74,6 +76,8 @@ private:
nsCOMPtr<nsICSSStyleSheet> mFormsSheet;
nsCOMPtr<nsICSSStyleSheet> mUserContentSheet;
nsCOMPtr<nsICSSStyleSheet> mUserChromeSheet;
nsCOMPtr<nsICSSStyleSheet> mUASheet;
nsCOMPtr<nsICSSStyleSheet> mQuirkSheet;
};
#endif

Просмотреть файл

@ -58,8 +58,6 @@
#include "nsIFrame.h"
#include "nsContentUtils.h"
nsIURI *nsStyleSet::gQuirkURI = 0;
nsStyleSet::nsStyleSet()
: mRuleTree(nsnull),
mRuleWalker(nsnull),
@ -75,12 +73,6 @@ nsStyleSet::nsStyleSet()
nsresult
nsStyleSet::Init(nsPresContext *aPresContext)
{
if (!gQuirkURI) {
static const char kQuirk_href[] = "resource://gre/res/quirk.css";
NS_NewURI(&gQuirkURI, kQuirk_href);
NS_ENSURE_TRUE(gQuirkURI, NS_ERROR_OUT_OF_MEMORY);
}
if (!BuildDefaultStyleData(aPresContext)) {
mDefaultStyleData.Destroy(0, aPresContext);
return NS_ERROR_OUT_OF_MEMORY;
@ -144,6 +136,16 @@ nsStyleSet::EndReconstruct()
mOldRuleTree = nsnull;
}
void
nsStyleSet::SetQuirkStyleSheet(nsIStyleSheet* aQuirkStyleSheet)
{
NS_ASSERTION(aQuirkStyleSheet, "Must have quirk sheet if this is called");
NS_ASSERTION(!mQuirkStyleSheet, "Multiple calls to SetQuirkStyleSheet?");
NS_ASSERTION(mSheets[eAgentSheet].IndexOf(aQuirkStyleSheet) != -1,
"Quirk style sheet not one of our agent sheets?");
mQuirkStyleSheet = aQuirkStyleSheet;
}
nsresult
nsStyleSet::GatherRuleProcessors(sheetType aType)
{
@ -341,50 +343,21 @@ nsStyleSet::EndUpdate()
void
nsStyleSet::EnableQuirkStyleSheet(PRBool aEnable)
{
if (!mQuirkStyleSheet) {
// first find the quirk sheet:
// - run through all of the agent sheets and check for a CSSStyleSheet that
// has the URL we want
PRInt32 nSheets = mSheets[eAgentSheet].Count();
for (PRInt32 i = 0; i < nSheets; ++i) {
nsIStyleSheet *sheet = mSheets[eAgentSheet].ObjectAt(i);
NS_ASSERTION(sheet, "mAgentSheets should not contain null sheets");
nsICSSStyleSheet *cssSheet = static_cast<nsICSSStyleSheet*>(sheet);
NS_ASSERTION(nsCOMPtr<nsICSSStyleSheet>(do_QueryInterface(sheet)) == cssSheet,
"Agent sheet must be a CSSStyleSheet");
nsCOMPtr<nsIStyleSheet> quirkSheet;
PRBool bHasSheet = PR_FALSE;
if (NS_SUCCEEDED(cssSheet->ContainsStyleSheet(gQuirkURI, bHasSheet,
getter_AddRefs(quirkSheet)))
&& bHasSheet) {
NS_ASSERTION(quirkSheet, "QuirkSheet must be set: ContainsStyleSheet is hosed");
// cache the sheet for faster lookup next time
mQuirkStyleSheet = quirkSheet;
// only one quirk style sheet can exist, so stop looking
break;
}
}
}
NS_ASSERTION(mQuirkStyleSheet, "no quirk stylesheet");
if (mQuirkStyleSheet) {
#ifdef DEBUG
if (mRuleProcessors[eAgentSheet]) {
static_cast<nsCSSRuleProcessor*>(static_cast<nsIStyleRuleProcessor*>(
mRuleProcessors[eAgentSheet]))->AssertQuirksChangeOK();
}
if (mRuleProcessors[eAgentSheet]) {
static_cast<nsCSSRuleProcessor*>(static_cast<nsIStyleRuleProcessor*>(
mRuleProcessors[eAgentSheet]))->AssertQuirksChangeOK();
}
#endif
#ifdef DEBUG_dbaron_off // XXX Make this |DEBUG| once it stops firing.
PRBool applicableNow;
mQuirkStyleSheet->GetApplicable(applicableNow);
NS_ASSERTION(!mRuleProcessors[eAgentSheet] || aEnable == applicableNow,
"enabling/disabling quirk stylesheet too late or incomplete quirk stylesheet");
if (mRuleProcessors[eAgentSheet] && aEnable == applicableNow)
printf("WARNING: We set the quirks mode too many times.\n"); // we do!
PRBool applicableNow;
mQuirkStyleSheet->GetApplicable(applicableNow);
NS_ASSERTION(!mRuleProcessors[eAgentSheet] || aEnable == applicableNow,
"enabling/disabling quirk stylesheet too late or incomplete quirk stylesheet");
if (mRuleProcessors[eAgentSheet] && aEnable == applicableNow)
printf("WARNING: We set the quirks mode too many times.\n"); // we do!
#endif
mQuirkStyleSheet->SetEnabled(aEnable);
}
mQuirkStyleSheet->SetEnabled(aEnable);
}
static PRBool

Просмотреть файл

@ -158,9 +158,6 @@ class nsStyleSet
mBindingManager = aBindingManager;
}
// Free global data at module shutdown
static void FreeGlobals() { NS_IF_RELEASE(gQuirkURI); }
// The "origins" of the CSS cascade, from lowest precedence to
// highest (for non-!important rules).
enum sheetType {
@ -209,6 +206,11 @@ class nsStyleSet
// Note: EndReconstruct should not be called if BeginReconstruct fails
void EndReconstruct();
// Let the style set know that a particular sheet is the quirks sheet. This
// sheet must already have been added to the UA sheets. The pointer must not
// be null. This should only be called once for a given style set.
void SetQuirkStyleSheet(nsIStyleSheet* aQuirkStyleSheet);
private:
// Not to be implemented
nsStyleSet(const nsStyleSet& aCopy);
@ -253,8 +255,6 @@ class nsStyleSet
nsPresContext* PresContext() { return mRuleTree->GetPresContext(); }
static nsIURI *gQuirkURI;
// The sheets in each array in mSheets are stored with the most significant
// sheet last.
nsCOMArray<nsIStyleSheet> mSheets[eSheetTypeCount];

Просмотреть файл

@ -36,7 +36,6 @@
@import url(resource://gre/res/html.css);
@import url(chrome://global/content/xul.css);
@import url(resource://gre/res/quirk.css);
@namespace parsererror url(http://www.mozilla.org/newlayout/xml/parsererror.xml);