Create DOM nodes for processing instructions in XUL. Bug 319654, patch by

Nickolay Ponomarev <asqueella@gmail.com>, r+sr=bzbarsky.
This commit is contained in:
bzbarsky%mit.edu 2006-11-08 02:25:37 +00:00
Родитель f0ab221e6d
Коммит ad42605c52
12 изменённых файлов: 546 добавлений и 353 удалений

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

@ -303,7 +303,7 @@ nsStyleLinkElement::UpdateStyleSheet(nsIDocument *aOldDocument,
parser, aObserver, &isAlternate);
}
if (NS_SUCCEEDED(rv) && parser && !doneLoading && !isAlternate) {
if (NS_SUCCEEDED(rv) && !doneLoading && !isAlternate) {
rv = NS_ERROR_HTMLPARSER_BLOCK;
}

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

@ -71,9 +71,22 @@ public:
NS_IMETHOD SetStyleSheet(nsIStyleSheet* aStyleSheet);
NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aStyleSheet);
NS_IMETHOD InitStyleLinkElement(nsIParser *aParser, PRBool aDontLoadStyle);
// If aForceUpdate == PR_TRUE will force the update even if the URI has not
// changed. This should be used in cases when something about the content
// that affects the resulting sheet changed but the URI may not have changed.
/**
* @param aForceUpdate when PR_TRUE, will force the update even if
* the URI has not changed. This should be used in cases when
* something about the content that affects the resulting sheet
* changed but the URI may not have changed.
* @returns NS_ERROR_HTMLPARSER_BLOCK if a non-alternate style sheet
* is being loaded asynchronously. In this case aObserver
* will be notified at a later stage when the sheet is
* loaded (if it is not null).
* @returns NS_OK in case when the update was successful, but the
* caller doesn't have to wait for a notification to
* aObserver. This can happen if there was no style sheet
* to load, when it's inline, or when it's alternate. Note
* that in the latter case aObserver is still notified about
* the load when it's done.
*/
NS_IMETHOD UpdateStyleSheet(nsIDocument *aOldDocument = nsnull,
nsICSSLoaderObserver* aObserver = nsnull,
PRBool aForceUpdate = PR_FALSE);

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

@ -2593,6 +2593,7 @@ nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream,
switch (child->mType) {
case eType_Element:
case eType_Text:
case eType_PI:
rv |= child->Serialize(aStream, aGlobal, aNodeInfos);
break;
case eType_Script:
@ -2699,6 +2700,15 @@ nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream,
return NS_ERROR_OUT_OF_MEMORY;
child->mType = childType;
rv |= child->Deserialize(aStream, aGlobal, aDocumentURI,
aNodeInfos);
break;
case eType_PI:
child = new nsXULPrototypePI();
if (! child)
return NS_ERROR_OUT_OF_MEMORY;
child->mType = childType;
rv |= child->Deserialize(aStream, aGlobal, aDocumentURI,
aNodeInfos);
break;
@ -3154,8 +3164,42 @@ nsXULPrototypeText::Deserialize(nsIObjectInputStream* aStream,
{
nsresult rv;
// Write basic prototype data
rv = aStream->ReadString(mValue);
return rv;
}
//----------------------------------------------------------------------
//
// nsXULPrototypePI
//
nsresult
nsXULPrototypePI::Serialize(nsIObjectOutputStream* aStream,
nsIScriptGlobalObject* aGlobal,
const nsCOMArray<nsINodeInfo> *aNodeInfos)
{
nsresult rv;
// Write basic prototype data
rv = aStream->Write32(mType);
rv |= aStream->WriteWStringZ(mTarget.get());
rv |= aStream->WriteWStringZ(mData.get());
return rv;
}
nsresult
nsXULPrototypePI::Deserialize(nsIObjectInputStream* aStream,
nsIScriptGlobalObject* aGlobal,
nsIURI* aDocumentURI,
const nsCOMArray<nsINodeInfo> *aNodeInfos)
{
nsresult rv;
rv = aStream->ReadString(mTarget);
rv |= aStream->ReadString(mData);
return rv;
}

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

@ -197,7 +197,7 @@ public:
class nsXULPrototypeNode
{
public:
enum Type { eType_Element, eType_Script, eType_Text };
enum Type { eType_Element, eType_Script, eType_Text, eType_PI };
Type mType;
@ -401,6 +401,36 @@ public:
nsString mValue;
};
class nsXULPrototypePI : public nsXULPrototypeNode
{
public:
nsXULPrototypePI()
: nsXULPrototypeNode(eType_PI)
{
NS_LOG_ADDREF(this, 1, ClassName(), ClassSize());
}
virtual ~nsXULPrototypePI()
{
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual const char* ClassName() { return "nsXULPrototypePI"; }
virtual PRUint32 ClassSize() { return sizeof(*this); }
#endif
virtual nsresult Serialize(nsIObjectOutputStream* aStream,
nsIScriptGlobalObject* aGlobal,
const nsCOMArray<nsINodeInfo> *aNodeInfos);
virtual nsresult Deserialize(nsIObjectInputStream* aStream,
nsIScriptGlobalObject* aGlobal,
nsIURI* aDocumentURI,
const nsCOMArray<nsINodeInfo> *aNodeInfos);
nsString mTarget;
nsString mData;
};
////////////////////////////////////////////////////////////////////////
/**

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

@ -35,16 +35,6 @@
*
* ***** END LICENSE BLOCK ***** */
/*
An XUL-specific extension to nsIDocument. Includes methods for
setting the root resource of the document content model, a factory
method for constructing the children of a node, etc.
XXX This should really be called nsIXULDocument.
*/
#ifndef nsIXULDocument_h___
#define nsIXULDocument_h___
@ -63,15 +53,16 @@ class nsIURI;
class nsIContent;
class nsIRDFDataSource;
// {7f9c0158-1da3-4279-9ee5-fa7931b94db1}
// {96736e80-4bd1-4a4e-974e-5d3d8e663f43}
#define NS_IXULDOCUMENT_IID \
{ 0x7f9c0158, 0x1da3, 0x4279, \
{ 0x9e, 0xe5, 0xfa, 0x79, 0x31, 0xb9, 0x4d, 0xb1 } }
{ 0x96736e80, 0x4bd1, 0x4a4e, \
{ 0x97, 0x4e, 0x5d, 0x3d, 0x8e, 0x66, 0x3f, 0x43 } }
/**
* XUL extensions to nsIDocument
/*
* An XUL-specific extension to nsIDocument. Includes methods for
* setting the root resource of the document content model, a factory
* method for constructing the children of a node, etc.
*/
class nsIXULDocument : public nsISupports
{
public:
@ -147,11 +138,16 @@ public:
NS_IMETHOD GetTemplateBuilderFor(nsIContent* aContent, nsIXULTemplateBuilder** aResult) = 0;
/**
* Callback notifying this document when its XUL prototype document load
* completes. The prototype load was initiated by another document load
* request than the one whose document is being notified here.
* This is invoked whenever the prototype for this document is loaded
* and should be walked, regardless of whether the XUL cache is
* disabled, whether the protototype was loaded, whether the
* prototype was loaded from the cache or created by parsing the
* actual XUL source, etc.
*
* @param aResumeWalk whether this should also call ResumeWalk().
* Sometimes the caller of OnPrototypeLoadDone resumes the walk itself
*/
NS_IMETHOD OnPrototypeLoadDone() = 0;
NS_IMETHOD OnPrototypeLoadDone(PRBool aResumeWalk) = 0;
/**
* Callback notifying when a document could not be parsed properly.

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

@ -130,7 +130,7 @@ const char XUL_FASTLOAD_FILE_BASENAME[] = "XUL";
// (opaque to XPCOM FastLoad code) format of XUL-specific XDR serializations.
// See also JSXDR_BYTECODE_VERSION in jsxdrapi.h, which tracks incompatible JS
// bytecode version changes.
#define XUL_FASTLOAD_FILE_VERSION (0xfeedbeef - 20)
#define XUL_FASTLOAD_FILE_VERSION (0xfeedbeef - 21)
#define XUL_SERIALIZATION_BUFFER_SIZE (64 * 1024)
#define XUL_DESERIALIZATION_BUFFER_SIZE (8 * 1024)

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

@ -35,55 +35,75 @@
*
* ***** END LICENSE BLOCK ***** */
/*
*/
#ifndef nsIXULPrototypeDocument_h__
#define nsIXULPrototypeDocument_h__
#include "nsISerializable.h"
#include "nsTArray.h"
#include "nsAString.h"
class nsIAtom;
class nsIPrincipal;
class nsIStyleSheet;
class nsIURI;
class nsString;
class nsVoidArray;
class nsXULPrototypeElement;
class nsXULPrototypePI;
class nsIXULDocument;
class nsNodeInfoManager;
class nsISupportsArray;
#define NS_IXULPROTOTYPEDOCUMENT_IID \
{ 0x726f0ab8, 0xb3cb, 0x11d8, { 0xb2, 0x67, 0x00, 0x0a, 0x95, 0xdc, 0x23, 0x4c } }
{0xfc69c0c7,0xd101,0x4830,{0xa1,0x3e,0x3a,0x65,0xbc,0xc8,0xee,0xf2}}
/**
* A "prototype" document that stores shared document information
* for the XUL cache.
*/
class nsIXULPrototypeDocument : public nsISerializable
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXULPROTOTYPEDOCUMENT_IID)
/**
* Retrieve the URI of the document
* Access the URI of the document
*/
NS_IMETHOD SetURI(nsIURI* aURI) = 0;
NS_IMETHOD GetURI(nsIURI** aResult) = 0;
/**
* Retrieve the root XULPrototype element of the document.
* Access the root nsXULPrototypeElement of the document.
*/
NS_IMETHOD GetRootElement(nsXULPrototypeElement** aResult) = 0;
NS_IMETHOD SetRootElement(nsXULPrototypeElement* aElement) = 0;
/**
* Add a processing instruction to the prolog. Note that only
* PI nodes are currently stored in a XUL prototype document's
* prolog and that they're handled separately from the rest of
* prototype node tree.
*
* @param aPI an already adrefed PI proto to add. This method takes
* ownership of the passed PI.
*/
NS_IMETHOD AddProcessingInstruction(nsXULPrototypePI* aPI) = 0;
/**
* @note GetProcessingInstructions retains the ownership (the PI
* protos only get deleted when the proto document is deleted)
*/
virtual const nsTArray<nsXULPrototypePI*>&
GetProcessingInstructions() const = 0;
/**
* Access the array of style overlays for this document.
*
* XXX shouldn't use nsISupportsArray here
*/
NS_IMETHOD AddStyleSheetReference(nsIURI* aStyleSheet) = 0;
NS_IMETHOD GetStyleSheetReferences(nsISupportsArray** aResult) = 0;
NS_IMETHOD AddOverlayReference(nsIURI* aURI) = 0;
NS_IMETHOD GetOverlayReferences(nsISupportsArray** aResult) = 0;
/**
* Access HTTP header data.
* @note Not implemented.
*/
NS_IMETHOD GetHeaderData(nsIAtom* aField, nsAString& aData) const = 0;
NS_IMETHOD SetHeaderData(nsIAtom* aField, const nsAString& aData) = 0;
@ -92,7 +112,20 @@ public:
virtual nsNodeInfoManager *GetNodeInfoManager() = 0;
NS_IMETHOD AwaitLoadDone(nsIXULDocument* aDocument, PRBool* aResult) = 0;
/**
* If current prototype document has not yet finished loading,
* appends aDocument to the list of documents to notify (via
* OnPrototypeLoadDone()) and sets aLoaded to PR_FALSE.
* Otherwise sets aLoaded to PR_TRUE.
*/
NS_IMETHOD AwaitLoadDone(nsIXULDocument* aDocument,
PRBool* aLoaded) = 0;
/**
* Notifies each document registered via AwaitLoadDone on this
* prototype document that the prototype has finished loading.
* The notification is performed by calling
* nsIXULDocument::OnPrototypeLoadDone on the registered documents.
*/
NS_IMETHOD NotifyLoadDone() = 0;
};

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

@ -40,16 +40,12 @@
* ***** END LICENSE BLOCK ***** */
/*
An implementation for a Gecko-style content sink that knows how
to build a content model from XUL.
For more information on XUL, see http://www.mozilla.org/xpfe
TO DO
-----
*/
* An implementation for a Gecko-style content sink that knows how
* to build a content model (the "prototype" document) from XUL.
*
* For more information on XUL,
* see http://developer.mozilla.org/en/docs/XUL
*/
#include "nsCOMPtr.h"
#include "nsForwardReference.h"
@ -114,7 +110,7 @@
static PRLogModuleInfo* gLog;
#endif
static NS_DEFINE_CID(kXULPrototypeCacheCID, NS_XULPROTOTYPECACHE_CID);
static NS_DEFINE_CID(kXULPrototypeCacheCID, NS_XULPROTOTYPECACHE_CID);
//----------------------------------------------------------------------
@ -186,14 +182,6 @@ protected:
nsAttrName &aName);
nsresult CreateElement(nsINodeInfo *aNodeInfo, nsXULPrototypeElement** aResult);
// Style sheets
nsresult ProcessStyleLink(nsIContent* aElement,
const nsString& aHref,
PRBool aAlternate,
const nsString& aTitle,
const nsString& aType,
const nsString& aMedia);
public:
enum State { eInProlog, eInDocumentElement, eInScript, eInEpilog };
@ -474,54 +462,6 @@ XULContentSinkImpl::SetParser(nsIParser* aParser)
return NS_OK;
}
nsresult
XULContentSinkImpl::ProcessStyleLink(nsIContent* aElement,
const nsString& aHref,
PRBool aAlternate,
const nsString& aTitle,
const nsString& aType,
const nsString& aMedia)
{
static const char kCSSType[] = "text/css";
nsresult rv = NS_OK;
if (aAlternate) { // if alternate, does it have title?
if (aTitle.IsEmpty()) { // alternates must have title
return NS_OK; //return without error, for now
}
}
nsAutoString mimeType;
nsAutoString params;
nsParserUtils::SplitMimeType(aType, mimeType, params);
if ((mimeType.IsEmpty()) || mimeType.EqualsIgnoreCase(kCSSType)) {
nsCOMPtr<nsIURI> url;
rv = NS_NewURI(getter_AddRefs(url), aHref, nsnull, mDocumentURL);
if (NS_OK != rv) {
return NS_OK; // The URL is bad, move along, don't propagate the error (for now)
}
// Add the style sheet reference to the prototype
mPrototype->AddStyleSheetReference(url);
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
if (! doc)
return NS_ERROR_FAILURE; // doc went away!
PRBool isAlternate;
rv = mCSSLoader->LoadStyleLink(aElement, url, aTitle, aMedia,
aAlternate, mParser, nsnull,
&isAlternate);
if (NS_SUCCEEDED(rv) && !isAlternate) {
rv = NS_ERROR_HTMLPARSER_BLOCK;
}
}
return rv;
}
NS_IMETHODIMP
XULContentSinkImpl::SetDocumentCharset(nsACString& aCharset)
{
@ -930,60 +870,36 @@ XULContentSinkImpl::HandleProcessingInstruction(const PRUnichar *aTarget,
{
FlushText();
// XXX For now, we don't add the PI to the content model.
// We just check for a style sheet PI
const nsDependentString target(aTarget);
const nsDependentString data(aData);
// Note: the created nsXULPrototypePI has mRefCnt == 1
nsXULPrototypePI* pi = new nsXULPrototypePI();
if (!pi)
return NS_ERROR_OUT_OF_MEMORY;
pi->mTarget = target;
pi->mData = data;
if (mState == eInProlog) {
// Note: passing in already addrefed pi
return mPrototype->AddProcessingInstruction(pi);
}
nsresult rv;
if (target.EqualsLiteral("xul-overlay")) {
// Load a XUL overlay.
nsAutoString href;
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::href, href);
// If there was no href, we can't do
// anything with this PI
if (href.IsEmpty()) {
return NS_OK;
}
// Add the overlay to our list of overlays that need to be processed.
nsCOMPtr<nsIURI> url;
rv = NS_NewURI(getter_AddRefs(url), href, nsnull, mDocumentURL);
if (NS_FAILED(rv)) {
// XXX This is wrong, the error message could be out of memory
// or something else equally bad, which we should propagate.
// Bad URL should probably be "success with info" value.
return NS_OK; // The URL is bad, move along. Don't propagate for now.
}
return mPrototype->AddOverlayReference(url);
nsVoidArray* children;
rv = mContextStack.GetTopChildren(&children);
if (NS_FAILED(rv)) {
pi->Release();
return rv;
}
if (!target.EqualsLiteral("xml-stylesheet")) {
return NS_OK;
if (!children->AppendElement(pi)) {
pi->Release();
return NS_ERROR_OUT_OF_MEMORY;
}
// It's a stylesheet PI...
nsAutoString type;
nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::type, type);
nsAutoString href, title, media;
PRBool isAlternate = PR_FALSE;
nsXMLContentSink::ParsePIData(data, href, title, media, isAlternate);
// If there was no href, we can't do anything with this PI
if (href.IsEmpty()) {
return NS_OK;
}
// XXX need a node here
rv = ProcessStyleLink(nsnull , href, isAlternate, title, type, media);
if (rv == NS_ERROR_HTMLPARSER_BLOCK && mParser) {
mParser->BlockParser();
}
return rv;
return NS_OK;
}

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

@ -82,11 +82,13 @@
#include "nsIDocShell.h"
#include "nsXULAtoms.h"
#include "nsHTMLAtoms.h"
#include "nsXMLContentSink.h"
#include "nsIXULContentSink.h"
#include "nsXULContentUtils.h"
#include "nsIXULOverlayProvider.h"
#include "nsIXULPrototypeCache.h"
#include "nsNetUtil.h"
#include "nsParserUtils.h"
#include "nsParserCIID.h"
#include "nsPIBoxObject.h"
#include "nsRDFCID.h"
@ -118,6 +120,7 @@
#include "nsIParserService.h"
#include "nsICSSStyleSheet.h"
#include "nsIScriptError.h"
#include "nsIStyleSheetLinkingElement.h"
#include "nsEventDispatcher.h"
#include "nsContentErrors.h"
#include "nsIObserverService.h"
@ -301,6 +304,7 @@ NS_INTERFACE_MAP_BEGIN(nsXULDocument)
NS_INTERFACE_MAP_ENTRY(nsIXULDocument)
NS_INTERFACE_MAP_ENTRY(nsIDOMXULDocument)
NS_INTERFACE_MAP_ENTRY(nsIStreamLoaderObserver)
NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XULDocument)
NS_INTERFACE_MAP_END_INHERITING(nsXMLDocument)
@ -341,6 +345,8 @@ nsXULDocument::SetContentType(const nsAString& aContentType)
// application/vnd.mozilla.xul+xml
}
// This is called when the master document begins loading, whether it's
// fastloaded or not.
nsresult
nsXULDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
nsILoadGroup* aLoadGroup,
@ -350,7 +356,7 @@ nsXULDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
{
// NOTE: If this ever starts calling nsDocument::StartDocumentLoad
// we'll possibly need to reset our content type afterwards.
mStillWalking = PR_TRUE;
mDocumentLoadGroup = do_GetWeakReference(aLoadGroup);
mDocumentTitle.SetIsVoid(PR_TRUE);
@ -413,14 +419,6 @@ nsXULDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
// Set up the right principal on ourselves.
SetPrincipal(proto->GetDocumentPrincipal());
// Add cloned style sheet references only if the prototype has in
// fact already loaded. It may still be loading when we hit the XUL
// prototype cache.
if (loaded) {
rv = AddPrototypeSheets();
if (NS_FAILED(rv)) return rv;
}
// We need a listener, even if proto is not yet loaded, in which
// event the listener's OnStopRequest method does nothing, and all
// the interesting work happens below nsXULDocument::EndLoad, from
@ -470,6 +468,8 @@ nsXULDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
return NS_OK;
}
// This gets invoked after a prototype for this document or one of
// its overlays is fully built in the content sink.
void
nsXULDocument::EndLoad()
{
@ -494,32 +494,32 @@ nsXULDocument::EndLoad()
// If the current prototype is an overlay document (non-master prototype)
// and we're filling the FastLoad disk cache, tell the cache we're done
// loading it, and write the prototype.
if (useXULCache && mIsWritingFastLoad &&
mMasterPrototype != mCurrentPrototype &&
isChrome)
// loading it, and write the prototype. The master prototype is put into
// the cache earlier in nsXULDocument::StartDocumentLoad.
if (useXULCache && mIsWritingFastLoad && isChrome &&
mMasterPrototype != mCurrentPrototype) {
gXULCache->WritePrototype(mCurrentPrototype);
}
if (isChrome) {
nsCOMPtr<nsIXULOverlayProvider> reg =
do_GetService(NS_CHROMEREGISTRY_CONTRACTID);
nsICSSLoader* cssLoader = CSSLoader();
if (reg) {
nsCOMPtr<nsISimpleEnumerator> overlays;
reg->GetStyleOverlays(uri, getter_AddRefs(overlays));
rv = reg->GetStyleOverlays(uri, getter_AddRefs(overlays));
if (NS_FAILED(rv)) return;
PRBool moreSheets;
nsCOMPtr<nsISupports> next;
nsCOMPtr<nsIURI> sheetURI;
nsCOMPtr<nsICSSStyleSheet> sheet;
while (NS_SUCCEEDED(rv = overlays->HasMoreElements(&moreSheets)) &&
moreSheets) {
overlays->GetNext(getter_AddRefs(next));
sheetURI = do_QueryInterface(next);
if (!uri) {
if (!sheetURI) {
NS_ERROR("Chrome registry handed me a non-nsIURI object!");
continue;
}
@ -527,19 +527,11 @@ nsXULDocument::EndLoad()
if (useXULCache && IsChromeURI(sheetURI)) {
mCurrentPrototype->AddStyleSheetReference(sheetURI);
}
cssLoader->LoadSheetSync(sheetURI, getter_AddRefs(sheet));
if (!sheet) {
NS_WARNING("Couldn't load chrome style overlay.");
continue;
}
AddStyleSheet(sheet);
}
}
if (useXULCache) {
// If it's a 'chrome:' prototype document, then notify any
// If it's a chrome prototype document, then notify any
// documents that raced to load the prototype, and awaited
// its load completion via proto->AwaitLoadDone().
rv = mCurrentPrototype->NotifyLoadDone();
@ -547,37 +539,26 @@ nsXULDocument::EndLoad()
}
}
// Now walk the prototype to build content.
rv = PrepareToWalk();
if (NS_FAILED(rv)) return;
ResumeWalk();
OnPrototypeLoadDone(PR_TRUE);
}
// Called back from nsXULPrototypeDocument::NotifyLoadDone for each XUL
// document that raced to start the same prototype document load, lost
// the race, but hit the XUL prototype cache because the winner filled
// the cache with the not-yet-loaded prototype object.
NS_IMETHODIMP
nsXULDocument::OnPrototypeLoadDone()
nsXULDocument::OnPrototypeLoadDone(PRBool aResumeWalk)
{
nsresult rv;
// Need to clone style sheet references now, as we couldn't do that
// in StartDocumentLoad, because the prototype may not have finished
// loading at that point.
// Add the style overlays from chrome registry, if any.
rv = AddPrototypeSheets();
if (NS_FAILED(rv)) return rv;
// Now we must do for each secondary or later XUL document (those that
// lost the race to start the prototype document load) what is done by
// nsCachedChromeStreamListener::OnStopRequest for the primary document
// (the one that won the race to start the prototype load).
rv = PrepareToWalk();
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to prepare for walk");
if (NS_FAILED(rv)) return rv;
return ResumeWalk();
if (aResumeWalk) {
rv = ResumeWalk();
}
return rv;
}
// called when an error occurs parsing a document
@ -1922,10 +1903,6 @@ nsXULDocument::Init()
// will persist.
mLocalStore = do_GetService(kLocalStoreCID);
// Create a new nsISupportsArray for dealing with overlay references
rv = NS_NewISupportsArray(getter_AddRefs(mUnloadedOverlays));
if (NS_FAILED(rv)) return rv;
if (gRefCnt++ == 0) {
// Keep the RDF service cached in a member variable to make using
// it a bit less painful
@ -2401,27 +2378,6 @@ nsXULDocument::PrepareToWalk()
// elements aren't yanked from beneath us.
mPrototypes.AppendObject(mCurrentPrototype);
// Push the overlay references onto our overlay processing
// stack. GetOverlayReferences() will return an ordered array of
// overlay references...
nsCOMPtr<nsISupportsArray> overlays;
rv = mCurrentPrototype->GetOverlayReferences(getter_AddRefs(overlays));
if (NS_FAILED(rv)) return rv;
// ...and we preserve this ordering by appending to our
// mUnloadedOverlays array in reverse order
PRUint32 count;
overlays->Count(&count);
for (PRInt32 i = count - 1; i >= 0; --i) {
nsISupports* isupports = overlays->ElementAt(i);
mUnloadedOverlays->AppendElement(isupports);
NS_IF_RELEASE(isupports);
}
// Now check the chrome registry for any additional overlays.
rv = AddChromeOverlays();
// Get the prototype's root element and initialize the context
// stack for the prototype walk.
nsXULPrototypeElement* proto;
@ -2448,11 +2404,33 @@ nsXULDocument::PrepareToWalk()
return NS_OK;
}
PRUint32 piInsertionPoint = 0;
if (mState != eState_Master) {
piInsertionPoint = IndexOf(GetRootContent());
NS_ASSERTION(piInsertionPoint >= 0,
"No root content when preparing to walk overlay!");
}
const nsTArray<nsXULPrototypePI*>& processingInstructions =
mCurrentPrototype->GetProcessingInstructions();
PRUint32 total = processingInstructions.Length();
for (PRUint32 i = 0; i < total; ++i) {
rv = CreateAndInsertPI(processingInstructions[i],
this, piInsertionPoint + i);
if (NS_FAILED(rv)) return rv;
}
// Now check the chrome registry for any additional overlays.
rv = AddChromeOverlays();
if (NS_FAILED(rv)) return rv;
// Do one-time initialization if we're preparing to walk the
// master document's prototype.
nsCOMPtr<nsIContent> root;
if (mState == eState_Master) {
// Add the root element
rv = CreateElementFromPrototype(proto, getter_AddRefs(root));
if (NS_FAILED(rv)) return rv;
@ -2485,6 +2463,112 @@ nsXULDocument::PrepareToWalk()
return NS_OK;
}
nsresult
nsXULDocument::CreateAndInsertPI(const nsXULPrototypePI* aProtoPI,
nsINode* aParent, PRUint32 aIndex)
{
NS_PRECONDITION(aProtoPI, "null ptr");
NS_PRECONDITION(aParent, "null ptr");
nsresult rv;
nsCOMPtr<nsIContent> node;
rv = NS_NewXMLProcessingInstruction(getter_AddRefs(node),
mNodeInfoManager,
aProtoPI->mTarget,
aProtoPI->mData);
if (NS_FAILED(rv)) return rv;
if (aProtoPI->mTarget.EqualsLiteral("xml-stylesheet")) {
rv = InsertXMLStylesheetPI(aProtoPI, aParent, aIndex, node);
} else if (aProtoPI->mTarget.EqualsLiteral("xul-overlay")) {
rv = InsertXULOverlayPI(aProtoPI, aParent, aIndex, node);
} else {
// No special processing, just add the PI to the document.
rv = aParent->InsertChildAt(node, aIndex, PR_FALSE);
}
return rv;
}
nsresult
nsXULDocument::InsertXMLStylesheetPI(const nsXULPrototypePI* aProtoPI,
nsINode* aParent,
PRUint32 aIndex,
nsIContent* aPINode)
{
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(aPINode));
NS_ASSERTION(ssle, "passed XML Stylesheet node does not "
"implement nsIStyleSheetLinkingElement!");
nsresult rv;
ssle->InitStyleLinkElement(nsnull, PR_FALSE);
// We want to be notified when the style sheet finishes loading, so
// disable style sheet loading for now.
ssle->SetEnableUpdates(PR_FALSE);
rv = aParent->InsertChildAt(aPINode, aIndex, PR_FALSE);
if (NS_FAILED(rv)) return rv;
ssle->SetEnableUpdates(PR_TRUE);
// load the stylesheet if necessary, passing ourselves as
// nsICSSObserver
rv = ssle->UpdateStyleSheet(nsnull, this);
if (rv == NS_ERROR_HTMLPARSER_BLOCK) {
++mPendingSheets;
return NS_OK;
}
return rv;
}
nsresult
nsXULDocument::InsertXULOverlayPI(const nsXULPrototypePI* aProtoPI,
nsINode* aParent,
PRUint32 aIndex,
nsIContent* aPINode)
{
nsresult rv;
rv = aParent->InsertChildAt(aPINode, aIndex, PR_FALSE);
if (NS_FAILED(rv)) return rv;
// xul-overlay PI is special only in prolog
if (!nsContentUtils::InProlog(aPINode)) {
return NS_OK;
}
nsAutoString href;
nsParserUtils::GetQuotedAttributeValue(aProtoPI->mData,
nsGkAtoms::href,
href);
// If there was no href, we can't do anything with this PI
if (href.IsEmpty()) {
return NS_OK;
}
// Add the overlay to our list of overlays that need to be processed.
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), href, nsnull, mDocumentURI);
if (NS_SUCCEEDED(rv)) {
// We insert overlays into mUnloadedOverlays at the same index in
// document order, so they end up in the reverse of the document
// order in mUnloadedOverlays.
// This is needed because the code in ResumeWalk loads the overlays
// by processing the last item of mUnloadedOverlays and removing it
// from the array.
rv = mUnloadedOverlays.InsertObjectAt(uri, 0);
} else if (rv == NS_ERROR_MALFORMED_URI) {
// The URL is bad, move along. Don't propagate for now.
rv = NS_OK;
}
return rv;
}
nsresult
nsXULDocument::AddChromeOverlays()
@ -2513,8 +2597,9 @@ nsXULDocument::AddChromeOverlays()
while (NS_SUCCEEDED(rv = overlays->HasMoreElements(&moreOverlays)) &&
moreOverlays) {
rv = overlays->GetNext(getter_AddRefs(next));
if (NS_FAILED(rv) || !next) continue;
if (NS_FAILED(rv) || !next) break;
uri = do_QueryInterface(next);
if (!uri) {
@ -2522,10 +2607,12 @@ nsXULDocument::AddChromeOverlays()
continue;
}
mUnloadedOverlays->AppendElement(uri);
// Same comment as in nsXULDocument::InsertXULOverlayPI
rv = mUnloadedOverlays.InsertObjectAt(uri, 0);
if (NS_FAILED(rv)) break;
}
return NS_OK;
return rv;
}
NS_IMETHODIMP
@ -2641,20 +2728,12 @@ nsXULDocument::LoadOverlayInternal(nsIURI* aURI, PRBool aIsDynamic,
return NS_OK;
}
// Found the overlay's prototype in the cache, fully loaded.
rv = AddPrototypeSheets();
if (NS_FAILED(rv)) return rv;
// Now prepare to walk the prototype to create its content
rv = PrepareToWalk();
if (NS_FAILED(rv)) return rv;
PR_LOG(gXULLog, PR_LOG_DEBUG, ("xul: overlay was cached"));
// If this is a dynamic overlay and we have the prototype in the chrome
// cache already, we must manually call ResumeWalk.
if (aIsDynamic)
return ResumeWalk();
// Found the overlay's prototype in the cache, fully loaded. If
// this is a dynamic overlay, this will call ResumeWalk.
// Otherwise, we'll return to ResumeWalk, which called us.
return OnPrototypeLoadDone(aIsDynamic);
}
else {
// Not there. Initiate a load.
@ -2754,9 +2833,12 @@ nsXULDocument::ResumeWalk()
while (mContextStack.Depth() > 0) {
// Look at the top of the stack to determine what we're
// currently working on.
// This will always be a node already constructed and
// inserted to the actual document.
nsXULPrototypeElement* proto;
nsCOMPtr<nsIContent> element;
PRInt32 indx;
PRInt32 indx; // all children of proto before indx (not
// inclusive) have already been constructed
rv = mContextStack.Peek(&proto, getter_AddRefs(element), &indx);
if (NS_FAILED(rv)) return rv;
@ -2901,6 +2983,19 @@ nsXULDocument::ResumeWalk()
}
}
break;
case nsXULPrototypeNode::eType_PI: {
nsXULPrototypePI* piProto =
NS_REINTERPRET_CAST(nsXULPrototypePI*, childproto);
rv = CreateAndInsertPI(piProto, element,
element->GetChildCount());
NS_ENSURE_SUCCESS(rv, rv);
}
break;
default:
NS_NOTREACHED("Unexpected nsXULPrototypeNode::Type value");
}
}
@ -2911,18 +3006,13 @@ nsXULDocument::ResumeWalk()
// If we're not already, mark us as now processing overlays.
mState = eState_Overlay;
PRUint32 count;
mUnloadedOverlays->Count(&count);
// If there are no overlay URIs, then we're done.
PRUint32 count = mUnloadedOverlays.Count();
if (! count)
break;
nsCOMPtr<nsIURI> uri =
dont_AddRef(NS_REINTERPRET_CAST(nsIURI*, mUnloadedOverlays->ElementAt(count - 1)));
mUnloadedOverlays->RemoveElementAt(count - 1);
nsCOMPtr<nsIURI> uri = mUnloadedOverlays[count-1];
mUnloadedOverlays.RemoveObjectAt(count-1);
PRBool shouldReturn, failureFromContent;
rv = LoadOverlayInternal(uri, PR_FALSE, &shouldReturn,
@ -2946,6 +3036,19 @@ nsXULDocument::ResumeWalk()
rv = ApplyPersistentAttributes();
if (NS_FAILED(rv)) return rv;
mStillWalking = PR_FALSE;
if (mPendingSheets == 0) {
rv = DoneWalking();
}
return rv;
}
nsresult
nsXULDocument::DoneWalking()
{
NS_PRECONDITION(mPendingSheets == 0, "there are sheets to be loaded");
NS_PRECONDITION(!mStillWalking, "walk not done");
// XXXldb This is where we should really be setting the chromehidden
// attribute.
@ -3048,7 +3151,28 @@ nsXULDocument::ResumeWalk()
}
}
return rv;
return NS_OK;
}
NS_IMETHODIMP
nsXULDocument::StyleSheetLoaded(nsICSSStyleSheet* aSheet,
PRBool aWasAlternate,
nsresult aStatus)
{
if (NS_SUCCEEDED(aStatus)) {
AddStyleSheet(aSheet);
}
NS_ASSERTION(mPendingSheets > 0,
"Unexpected StyleSheetLoaded notification");
--mPendingSheets;
if (!mStillWalking && mPendingSheets == 0) {
return DoneWalking();
}
return NS_OK;
}
void
@ -3594,7 +3718,6 @@ nsXULDocument::CreateTemplateBuilder(nsIContent* aElement)
nsresult
nsXULDocument::AddPrototypeSheets()
{
// Add mCurrentPrototype's style sheets to the document.
nsresult rv;
nsCOMPtr<nsISupportsArray> sheets;
@ -3609,36 +3732,14 @@ nsXULDocument::AddPrototypeSheets()
NS_IF_RELEASE(isupports);
NS_ASSERTION(uri, "not a URI!!!");
if (! uri)
return NS_ERROR_UNEXPECTED;
nsCAutoString spec;
uri->GetAsciiSpec(spec);
rv = CSSLoader()->LoadSheet(uri, this);
if (!IsChromeURI(uri)) {
// These don't get to be in the prototype cache anyway...
// and we can't load non-chrome sheets synchronously
continue;
}
nsCOMPtr<nsICSSStyleSheet> sheet;
// If the sheet is a chrome URL, then we can refetch the sheet
// synchronously, since we know the sheet is local. It's not
// too late! :) If we're lucky, the loader will just pull it
// from the prototype cache anyway.
// Otherwise we just bail. It shouldn't currently
// be possible to get into this situation for any reason
// other than a skin switch anyway (since skin switching is the
// only system that partially invalidates the XUL cache).
// - dwh
//XXXbz we hit this code from fastload all the time. Bug 183505.
rv = CSSLoader()->LoadSheetSync(uri, getter_AddRefs(sheet));
// XXXldb We need to prevent bogus sheets from being held in the
// prototype's list, but until then, don't propagate the failure
// from LoadSheetSync (and thus exit the loop).
// from LoadSheet (and thus exit the loop).
if (NS_SUCCEEDED(rv)) {
AddStyleSheet(sheet);
++mPendingSheets;
}
}
@ -4247,12 +4348,7 @@ nsXULDocument::CachedChromeStreamListener::OnStopRequest(nsIRequest *request,
if (! mProtoLoaded)
return NS_OK;
nsresult rv;
rv = mDocument->PrepareToWalk();
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to prepare for walk");
if (NS_FAILED(rv)) return rv;
return mDocument->ResumeWalk();
return mDocument->OnPrototypeLoadDone(PR_TRUE);
}

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

@ -55,6 +55,7 @@
#include "nsIXULPrototypeDocument.h"
#include "nsScriptLoader.h"
#include "nsIStreamListener.h"
#include "nsICSSLoaderObserver.h"
class nsIRDFResource;
class nsIRDFService;
@ -83,7 +84,8 @@ struct PRLogModuleInfo;
class nsXULDocument : public nsXMLDocument,
public nsIXULDocument,
public nsIDOMXULDocument,
public nsIStreamLoaderObserver
public nsIStreamLoaderObserver,
public nsICSSLoaderObserver
{
public:
nsXULDocument();
@ -141,7 +143,7 @@ public:
nsIXULTemplateBuilder* aBuilder);
NS_IMETHOD GetTemplateBuilderFor(nsIContent* aContent,
nsIXULTemplateBuilder** aResult);
NS_IMETHOD OnPrototypeLoadDone();
NS_IMETHOD OnPrototypeLoadDone(PRBool aResumeWalk);
PRBool OnDocumentParserError();
// nsIDOMNode interface overrides
@ -157,6 +159,11 @@ public:
// nsIDOMNSDocument
NS_IMETHOD GetContentType(nsAString& aContentType);
// nsICSSLoaderObserver
NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet* aSheet,
PRBool aWasAlternate,
nsresult aStatus);
static PRBool
MatchAttribute(nsIContent* aContent,
PRInt32 aNameSpaceID,
@ -259,19 +266,29 @@ protected:
nsElementMap mElementMap;
nsCOMPtr<nsIRDFDataSource> mLocalStore;
PRPackedBool mIsPopup;
PRPackedBool mIsFastLoad;
PRPackedBool mApplyingPersistedAttrs;
PRPackedBool mIsWritingFastLoad;
PRPackedBool mDocumentLoaded;
/**
* Since ResumeWalk is interruptible, it's possible that last
* stylesheet finishes loading while the PD walk is still in
* progress (waiting for an overlay to finish loading).
* mStillWalking prevents DoneLoading (and StartLayout) from being
* called in this situation.
*/
PRPackedBool mStillWalking;
nsCOMPtr<nsIDOMXULCommandDispatcher> mCommandDispatcher; // [OWNER] of the focus tracker
// Maintains the template builders that have been attached to
// content elements
nsSupportsHashtable* mTemplateBuilderTable;
nsVoidArray mForwardReferences;
nsForwardReference::Phase mResolutionPhase;
PRUint32 mPendingSheets;
/*
* XXX dr
* ------
@ -333,8 +350,13 @@ protected:
* order of the array is significant: overlays at the _end_ of the
* array are resolved before overlays earlier in the array (i.e.,
* it is a stack).
*
* In the current implementation the order the overlays are loaded
* in is as follows: first overlays from xul-overlay PIs, in the
* same order as in the document, then the overlays from the chrome
* registry.
*/
nsCOMPtr<nsISupportsArray> mUnloadedOverlays;
nsCOMArray<nsIURI> mUnloadedOverlays;
/**
* Load the transcluded script at the specified URI. If the
@ -394,7 +416,8 @@ protected:
CreateTemplateBuilder(nsIContent* aElement);
/**
* Add the current prototype's style sheets to the document.
* Add the current prototype's style sheets (currently it's just
* style overlays from the chrome registry) to the document.
*/
nsresult AddPrototypeSheets();
@ -517,6 +540,39 @@ protected:
*/
nsresult PrepareToWalk();
/**
* Creates a processing instruction based on aProtoPI and inserts
* it to the DOM (as the aIndex-th child of aParent).
*/
nsresult
CreateAndInsertPI(const nsXULPrototypePI* aProtoPI,
nsINode* aParent, PRUint32 aIndex);
/**
* Inserts the passed <?xml-stylesheet ?> PI at the specified
* index. Loads and applies the associated stylesheet
* asynchronously.
* The prototype document walk can happen before the stylesheets
* are loaded, but the final steps in the load process (see
* DoneWalking()) are not run before all the stylesheets are done
* loading.
*/
nsresult
InsertXMLStylesheetPI(const nsXULPrototypePI* aProtoPI,
nsINode* aParent,
PRUint32 aIndex,
nsIContent* aPINode);
/**
* Inserts the passed <?xul-overlay ?> PI at the specified index.
* Schedules the referenced overlay URI for further processing.
*/
nsresult
InsertXULOverlayPI(const nsXULPrototypePI* aProtoPI,
nsINode* aParent,
PRUint32 aIndex,
nsIContent* aPINode);
/**
* Add overlays from the chrome registry to the set of unprocessed
* overlays still to do.
@ -529,6 +585,13 @@ protected:
*/
nsresult ResumeWalk();
/**
* Called at the end of ResumeWalk() and from StyleSheetLoaded().
* Expects that both the prototype document walk is complete and
* all referenced stylesheets finished loading.
*/
nsresult DoneWalking();
/**
* Report that an overlay failed to load
* @param aURI the URI of the overlay that failed to load

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

@ -40,11 +40,9 @@
* ***** END LICENSE BLOCK ***** */
/*
A "prototype" document that stores shared document information
for the XUL cache.
*/
* A "prototype" document that stores shared document information
* for the XUL cache.
*/
#include "nsCOMPtr.h"
#include "nsAString.h"
@ -64,7 +62,6 @@
#include "nsIXULPrototypeDocument.h"
#include "jsapi.h"
#include "nsString.h"
#include "nsVoidArray.h"
#include "nsXULElement.h"
#include "nsIConsoleService.h"
#include "nsIScriptError.h"
@ -135,12 +132,12 @@ public:
NS_IMETHOD GetRootElement(nsXULPrototypeElement** aResult);
NS_IMETHOD SetRootElement(nsXULPrototypeElement* aElement);
NS_IMETHOD AddProcessingInstruction(nsXULPrototypePI* aPI);
const nsTArray<nsXULPrototypePI*>& GetProcessingInstructions() const;
NS_IMETHOD AddStyleSheetReference(nsIURI* aStyleSheet);
NS_IMETHOD GetStyleSheetReferences(nsISupportsArray** aResult);
NS_IMETHOD AddOverlayReference(nsIURI* aURI);
NS_IMETHOD GetOverlayReferences(nsISupportsArray** aResult);
NS_IMETHOD GetHeaderData(nsIAtom* aField, nsAString& aData) const;
NS_IMETHOD SetHeaderData(nsIAtom* aField, const nsAString& aData);
@ -160,8 +157,8 @@ public:
protected:
nsCOMPtr<nsIURI> mURI;
nsXULPrototypeElement* mRoot;
nsTArray<nsXULPrototypePI*> mProcessingInstructions;
nsCOMPtr<nsISupportsArray> mStyleSheetReferences;
nsCOMPtr<nsISupportsArray> mOverlayReferences;
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
nsCOMPtr<nsIScriptGlobalObject> mGlobalObject;
@ -250,9 +247,6 @@ nsXULPrototypeDocument::Init()
rv = NS_NewISupportsArray(getter_AddRefs(mStyleSheetReferences));
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_NewISupportsArray(getter_AddRefs(mOverlayReferences));
NS_ENSURE_SUCCESS(rv, rv);
mNodeInfoManager = new nsNodeInfoManager();
NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_OUT_OF_MEMORY);
@ -265,7 +259,13 @@ nsXULPrototypeDocument::~nsXULPrototypeDocument()
// cleaup cycles etc.
mGlobalObject->SetGlobalObjectOwner(nsnull);
}
PRUint32 count = mProcessingInstructions.Length();
for (PRUint32 i = 0; i < count; i++)
{
mProcessingInstructions[i]->Release();
}
if (mRoot)
mRoot->ReleaseSubtree();
@ -366,14 +366,6 @@ nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream)
mStyleSheetReferences->AppendElement(referenceURI);
}
// nsISupportsArray mOverlayReferences
rv |= aStream->Read32(&referenceCount);
for (i = 0; i < referenceCount; ++i) {
rv |= aStream->ReadObject(PR_TRUE, getter_AddRefs(referenceURI));
mOverlayReferences->AppendElement(referenceURI);
}
// nsIPrincipal mDocumentPrincipal
nsCOMPtr<nsIPrincipal> principal;
rv |= NS_ReadOptionalObject(aStream, PR_TRUE, getter_AddRefs(principal));
@ -412,12 +404,27 @@ nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream)
// Document contents
PRUint32 type;
rv |= aStream->Read32(&type);
while (NS_SUCCEEDED(rv)) {
rv |= aStream->Read32(&type);
if ((nsXULPrototypeNode::Type)type != nsXULPrototypeNode::eType_Element)
return NS_ERROR_FAILURE;
if ((nsXULPrototypeNode::Type)type == nsXULPrototypeNode::eType_PI) {
nsXULPrototypePI* pi = new nsXULPrototypePI();
if (! pi) {
rv |= NS_ERROR_OUT_OF_MEMORY;
break;
}
rv |= mRoot->Deserialize(aStream, mGlobalObject, mURI, &nodeInfos);
rv |= pi->Deserialize(aStream, mGlobalObject, mURI, &nodeInfos);
rv |= AddProcessingInstruction(pi);
} else if ((nsXULPrototypeNode::Type)type == nsXULPrototypeNode::eType_Element) {
rv |= mRoot->Deserialize(aStream, mGlobalObject, mURI, &nodeInfos);
break;
} else {
NS_NOTREACHED("Unexpected prototype node type");
rv |= NS_ERROR_FAILURE;
break;
}
}
rv |= NotifyLoadDone();
return rv;
@ -491,16 +498,6 @@ nsXULPrototypeDocument::Write(nsIObjectOutputStream* aStream)
rv |= aStream->WriteCompoundObject(referenceURI, NS_GET_IID(nsIURI), PR_TRUE);
}
// nsISupportsArray mOverlayReferences
mOverlayReferences->Count(&referenceCount);
rv |= aStream->Write32(referenceCount);
for (i = 0; i < referenceCount; ++i) {
mOverlayReferences->QueryElementAt(i, NS_GET_IID(nsIURI), getter_AddRefs(referenceURI));
rv |= aStream->WriteCompoundObject(referenceURI, NS_GET_IID(nsIURI), PR_TRUE);
}
// nsIPrincipal mDocumentPrincipal
rv |= NS_WriteOptionalObject(aStream, mDocumentPrincipal, PR_TRUE);
@ -528,6 +525,12 @@ nsXULPrototypeDocument::Write(nsIObjectOutputStream* aStream)
nsIScriptGlobalObject* globalObject = GetScriptGlobalObject();
NS_ENSURE_TRUE(globalObject, NS_ERROR_UNEXPECTED);
referenceCount = mProcessingInstructions.Length();
for (i = 0; i < referenceCount; ++i) {
nsXULPrototypePI* pi = mProcessingInstructions[i];
rv |= pi->Serialize(aStream, globalObject, &nodeInfos);
}
if (mRoot)
rv |= mRoot->Serialize(aStream, globalObject, &nodeInfos);
@ -581,16 +584,30 @@ nsXULPrototypeDocument::SetRootElement(nsXULPrototypeElement* aElement)
return NS_OK;
}
NS_IMETHODIMP
nsXULPrototypeDocument::AddProcessingInstruction(nsXULPrototypePI* aPI)
{
NS_PRECONDITION(aPI, "null ptr");
if (!mProcessingInstructions.AppendElement(aPI)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
const nsTArray<nsXULPrototypePI*>&
nsXULPrototypeDocument::GetProcessingInstructions() const
{
return mProcessingInstructions;
}
NS_IMETHODIMP
nsXULPrototypeDocument::AddStyleSheetReference(nsIURI* aURI)
{
NS_PRECONDITION(aURI != nsnull, "null ptr");
NS_PRECONDITION(aURI, "null ptr");
if (! aURI)
return NS_ERROR_NULL_POINTER;
mStyleSheetReferences->AppendElement(aURI);
return NS_OK;
return mStyleSheetReferences->AppendElement(aURI);
}
@ -602,29 +619,6 @@ nsXULPrototypeDocument::GetStyleSheetReferences(nsISupportsArray** aResult)
return NS_OK;
}
NS_IMETHODIMP
nsXULPrototypeDocument::AddOverlayReference(nsIURI* aURI)
{
NS_PRECONDITION(aURI != nsnull, "null ptr");
if (! aURI)
return NS_ERROR_NULL_POINTER;
mOverlayReferences->AppendElement(aURI);
return NS_OK;
}
NS_IMETHODIMP
nsXULPrototypeDocument::GetOverlayReferences(nsISupportsArray** aResult)
{
*aResult = mOverlayReferences;
NS_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsXULPrototypeDocument::GetHeaderData(nsIAtom* aField, nsAString& aData) const
{
@ -718,6 +712,11 @@ nsXULPrototypeDocument::AwaitLoadDone(nsIXULDocument* aDocument, PRBool* aResult
NS_IMETHODIMP
nsXULPrototypeDocument::NotifyLoadDone()
{
// Call back to each XUL document that raced to start the same
// prototype document load, lost the race, but hit the XUL
// prototype cache because the winner filled the cache with
// the not-yet-loaded prototype object.
nsresult rv = NS_OK;
mLoaded = PR_TRUE;
@ -731,7 +730,9 @@ nsXULPrototypeDocument::NotifyLoadDone()
rv = mPrototypeWaiters->GetElementAt(i, getter_AddRefs(doc));
if (NS_FAILED(rv)) break;
rv = doc->OnPrototypeLoadDone();
// PR_TRUE means that OnPrototypeLoadDone will also
// call ResumeWalk().
rv = doc->OnPrototypeLoadDone(PR_TRUE);
if (NS_FAILED(rv)) break;
}
}

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

@ -55,7 +55,8 @@ public:
/**
* StyleSheetLoaded is called after aSheet is marked complete and before any
* load events associated with aSheet are fired.
* @param aSheet the sheet that was loaded
* @param aSheet the sheet that was loaded. Guaranteed to always be
* non-null, even if aStatus indicates failure.
* @param aWasAlternate whether the sheet was an alternate. This will always
* match the value LoadStyleLink or LoadInlineStyle returned in
* aIsAlternate if one of those methods were used to load the sheet,