зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
f0ab221e6d
Коммит
ad42605c52
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче