Bug 18392. Use XUL document cache for retrieving master document.

This commit is contained in:
waterson%netscape.com 1999-12-04 07:45:57 +00:00
Родитель e634ed06f2
Коммит 82fb1998b7
8 изменённых файлов: 702 добавлений и 510 удалений

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

@ -20,20 +20,227 @@
* Contributor(s):
*/
#include "nsChromeProtocolHandler.h"
#include "nsCOMPtr.h"
#include "nsCRT.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIIOService.h"
#include "nsChromeProtocolHandler.h"
#include "nsIChannel.h"
#include "nsIChromeRegistry.h"
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsIComponentManager.h"
#include "nsIIOService.h"
#include "nsILoadGroup.h"
#include "nsIScriptSecurityManager.h"
#include "nsIStreamListener.h"
#include "nsIServiceManager.h"
#include "nsIXULDocument.h"
#include "nsIXULPrototypeCache.h"
#include "nsIXULPrototypeDocument.h"
#include "nsRDFCID.h"
#include "nsXPIDLString.h"
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kChromeRegistryCID, NS_CHROMEREGISTRY_CID);
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
static NS_DEFINE_CID(kXULDocumentCID, NS_XULDOCUMENT_CID);
static NS_DEFINE_CID(kXULPrototypeCacheCID, NS_XULPROTOTYPECACHE_CID);
//----------------------------------------------------------------------
//
// A channel that's used for loading cached chrome documents.
//
class nsCachedChromeChannel : public nsIChannel
{
protected:
nsCachedChromeChannel(const char* aCommand, nsIURI* aURI);
virtual ~nsCachedChromeChannel();
const char* mCommand;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsILoadGroup> mLoadGroup;
public:
static nsresult
Create(const char* aCommand, nsIURI* aURI, nsIChannel** aResult);
NS_DECL_ISUPPORTS
// nsIRequest
NS_IMETHOD IsPending(PRBool *_retval) { *_retval = PR_TRUE; return NS_OK; }
NS_IMETHOD Cancel(void) { return NS_OK; }
NS_IMETHOD Suspend(void) { return NS_OK; }
NS_IMETHOD Resume(void) { return NS_OK; }
// nsIChannel
NS_DECL_NSICHANNEL
};
NS_IMPL_ADDREF(nsCachedChromeChannel);
NS_IMPL_RELEASE(nsCachedChromeChannel);
NS_IMPL_QUERY_INTERFACE2(nsCachedChromeChannel, nsIRequest, nsIChannel);
nsresult
nsCachedChromeChannel::Create(const char* aCommand, nsIURI* aURI, nsIChannel** aResult)
{
NS_PRECONDITION(aURI != nsnull, "null ptr");
if (! aURI)
return NS_ERROR_NULL_POINTER;
nsCachedChromeChannel* channel = new nsCachedChromeChannel(aCommand, aURI);
if (! channel)
return NS_ERROR_OUT_OF_MEMORY;
*aResult = channel;
NS_ADDREF(*aResult);
return NS_OK;
}
nsCachedChromeChannel::nsCachedChromeChannel(const char* aCommand, nsIURI* aURI)
: mCommand(aCommand),
mURI(aURI)
{
NS_INIT_REFCNT();
}
nsCachedChromeChannel::~nsCachedChromeChannel()
{
}
NS_IMETHODIMP
nsCachedChromeChannel::GetOriginalURI(nsIURI * *aOriginalURI)
{
*aOriginalURI = mURI;
NS_ADDREF(*aOriginalURI);
return NS_OK;
}
NS_IMETHODIMP
nsCachedChromeChannel::GetURI(nsIURI * *aURI)
{
*aURI = mURI;
NS_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP
nsCachedChromeChannel::OpenInputStream(PRUint32 startPosition, PRInt32 readCount, nsIInputStream **_retval)
{
NS_NOTREACHED("don't do that");
*_retval = nsnull;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream **_retval)
{
NS_NOTREACHED("don't do that");
*_retval = nsnull;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports *ctxt)
{
NS_NOTREACHED("don't do that");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount, nsISupports *ctxt, nsIStreamListener *listener)
{
if (listener) {
nsresult rv;
rv = listener->OnStartRequest(this, ctxt);
(void) listener->OnStopRequest(this, ctxt, rv, nsnull);
}
return NS_OK;
}
NS_IMETHODIMP
nsCachedChromeChannel::AsyncWrite(nsIInputStream *fromStream, PRUint32 startPosition, PRInt32 writeCount, nsISupports *ctxt, nsIStreamObserver *observer)
{
NS_NOTREACHED("don't do that");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
{
*aLoadAttributes = nsIChannel::LOAD_NORMAL;
return NS_OK;
}
NS_IMETHODIMP
nsCachedChromeChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
NS_NOTREACHED("don't do that");
return NS_OK;
}
NS_IMETHODIMP
nsCachedChromeChannel::GetContentType(char * *aContentType)
{
*aContentType = nsXPIDLCString::Copy("text/xul");
return *aContentType ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
NS_IMETHODIMP
nsCachedChromeChannel::GetContentLength(PRInt32 *aContentLength)
{
NS_NOTREACHED("don't do that");
*aContentLength = 0;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::GetOwner(nsISupports * *aOwner)
{
NS_NOTREACHED("don't do that");
*aOwner = nsnull;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::SetOwner(nsISupports * aOwner)
{
NS_NOTREACHED("don't do that");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::GetLoadGroup(nsILoadGroup * *aLoadGroup)
{
*aLoadGroup = mLoadGroup;
NS_IF_ADDREF(*aLoadGroup);
return NS_OK;
}
NS_IMETHODIMP
nsCachedChromeChannel::SetLoadGroup(nsILoadGroup * aLoadGroup)
{
mLoadGroup = aLoadGroup;
return NS_OK;
}
NS_IMETHODIMP
nsCachedChromeChannel::GetNotificationCallbacks(nsIInterfaceRequestor * *aNotificationCallbacks)
{
NS_NOTREACHED("don't do that");
*aNotificationCallbacks = nsnull;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::SetNotificationCallbacks(nsIInterfaceRequestor * aNotificationCallbacks)
{
NS_NOTREACHED("don't do that");
return NS_ERROR_FAILURE;
}
////////////////////////////////////////////////////////////////////////////////
@ -124,53 +331,73 @@ nsChromeProtocolHandler::NewURI(const char *aSpec, nsIURI *aBaseURI,
}
NS_IMETHODIMP
nsChromeProtocolHandler::NewChannel(const char* verb, nsIURI* uri,
nsChromeProtocolHandler::NewChannel(const char* aVerb, nsIURI* aURI,
nsILoadGroup* aLoadGroup,
nsIInterfaceRequestor* notificationCallbacks,
nsLoadFlags loadAttributes,
nsIURI* originalURI,
nsIChannel* *result)
nsIInterfaceRequestor* aNotificationCallbacks,
nsLoadFlags aLoadAttributes,
nsIURI* aOriginalURI,
nsIChannel* *aResult)
{
nsresult rv;
NS_WITH_SERVICE(nsIChromeRegistry, reg, kChromeRegistryCID, &rv);
nsCOMPtr<nsIChannel> result;
// First check the prototype cache to see if we've already got the
// document in the cache.
NS_WITH_SERVICE(nsIXULPrototypeCache, cache, kXULPrototypeCacheCID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIURI> chromeURI;
rv = uri->Clone(getter_AddRefs(chromeURI)); // don't mangle the original
nsCOMPtr<nsIXULPrototypeDocument> proto;
rv = cache->GetPrototype(aURI, getter_AddRefs(proto));
if (NS_FAILED(rv)) return rv;
rv = reg->ConvertChromeURL(chromeURI);
if (NS_FAILED(rv)) return rv;
if (proto) {
// ...in which case, we'll create a dummy stream that'll just
// load the thing.
rv = nsCachedChromeChannel::Create(aVerb, aURI, getter_AddRefs(result));
if (NS_FAILED(rv)) return rv;
}
else {
// Miss. Resolve the chrome URL using the registry and do a
// normal necko load.
NS_WITH_SERVICE(nsIChromeRegistry, reg, kChromeRegistryCID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIURI> chromeURI;
rv = aURI->Clone(getter_AddRefs(chromeURI)); // don't mangle the original
if (NS_FAILED(rv)) return rv;
// now fetch the converted URI
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = reg->ConvertChromeURL(chromeURI);
if (NS_FAILED(rv)) return rv;
rv = serv->NewChannelFromURI(verb, chromeURI,
aLoadGroup,
notificationCallbacks,
loadAttributes,
originalURI ? originalURI : uri, result);
// now fetch the converted URI
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = serv->NewChannelFromURI(aVerb, chromeURI,
aLoadGroup,
aNotificationCallbacks,
aLoadAttributes,
aOriginalURI ? aOriginalURI : aURI,
getter_AddRefs(result));
if (NS_FAILED(rv)) return rv;
// Get a system principal for chrome and set the owner
// property of the result
NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager, NS_SCRIPTSECURITYMANAGER_PROGID, &rv);
if (NS_FAILED(rv)) return rv;
// Get a system principal for chrome and set the owner property
// of the result
if (NS_SUCCEEDED(rv)) {
nsresult rv2;
NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager,
NS_SCRIPTSECURITYMANAGER_PROGID, &rv2);
if (NS_FAILED(rv2))
return NS_ERROR_FAILURE;
nsCOMPtr<nsIPrincipal> principal;
if (NS_FAILED(securityManager->GetSystemPrincipal(getter_AddRefs(principal))))
{
return NS_ERROR_FAILURE;
}
rv = securityManager->GetSystemPrincipal(getter_AddRefs(principal));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISupports> owner = do_QueryInterface(principal);
(*result)->SetOwner(owner);
result->SetOwner(owner);
}
return rv;
*aResult = result;
NS_ADDREF(*aResult);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////

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

@ -101,13 +101,10 @@ public:
*/
NS_IMETHOD AddForwardReference(nsForwardReference* aForwardReference) = 0;
NS_IMETHOD ResolveForwardReferences() = 0;
/**
* Create a XUL document from a prototype
* Resolve the all of the document's forward references.
*/
NS_IMETHOD CreateFromPrototype(const char* aCommand,
nsIXULPrototypeDocument* aPrototype) = 0;
NS_IMETHOD ResolveForwardReferences() = 0;
};
// factory functions

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

@ -615,8 +615,6 @@ nsXULDocument::StartDocumentLoad(const char* aCommand,
nsISupports* aContainer,
nsIStreamListener **aDocListener)
{
nsresult rv;
#if defined(DEBUG_waterson) || defined(DEBUG_hyatt)
mLoadStart = PR_Now();
@ -627,22 +625,50 @@ nsXULDocument::StartDocumentLoad(const char* aCommand,
}
#endif
nsCOMPtr<nsIURI> url;
rv = aChannel->GetURI(getter_AddRefs(url));
nsresult rv;
mCommand = aCommand;
mDocumentLoadGroup = getter_AddRefs(NS_GetWeakReference(aLoadGroup));
mDocumentTitle.Truncate();
rv = aChannel->GetOriginalURI(getter_AddRefs(mDocumentURL));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIParser> parser;
rv = PrepareToLoad(aContainer, aCommand, aChannel, aLoadGroup, getter_AddRefs(parser));
rv = PrepareStyleSheets(mDocumentURL);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIStreamListener> listener = do_QueryInterface(parser, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "parser doesn't support nsIStreamListener");
// Look in the chrome cache: see if we've got this puppy loaded
// already.
nsCOMPtr<nsIXULPrototypeDocument> proto;
rv = gXULCache->GetPrototype(mDocumentURL, getter_AddRefs(proto));
if (NS_FAILED(rv)) return rv;
*aDocListener = listener;
if (proto) {
mMasterPrototype = mCurrentPrototype = proto;
rv = AddPrototypeSheets();
if (NS_FAILED(rv)) return rv;
*aDocListener = new CachedChromeStreamListener(this);
if (! *aDocListener)
return NS_ERROR_OUT_OF_MEMORY;
}
else {
nsCOMPtr<nsIParser> parser;
rv = PrepareToLoad(aContainer, aCommand, aChannel, aLoadGroup, getter_AddRefs(parser));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIStreamListener> listener = do_QueryInterface(parser, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "parser doesn't support nsIStreamListener");
if (NS_FAILED(rv)) return rv;
*aDocListener = listener;
parser->Parse(mDocumentURL);
}
NS_IF_ADDREF(*aDocListener);
parser->Parse(url);
return NS_OK;
}
@ -1229,8 +1255,7 @@ nsXULDocument::EndLoad()
rv = PrepareToWalk();
if (NS_FAILED(rv)) return rv;
rv = ResumeWalk();
return rv;
return ResumeWalk();
}
@ -1997,77 +2022,6 @@ nsXULDocument::ResolveForwardReferences()
}
NS_IMETHODIMP
nsXULDocument::CreateFromPrototype(const char* aCommand,
nsIXULPrototypeDocument* aPrototype)
{
nsresult rv;
mMasterPrototype = mCurrentPrototype = aPrototype;
rv = mCurrentPrototype->GetURI(getter_AddRefs(mDocumentURL));
if (NS_FAILED(rv)) return rv;
rv = PrepareStyleSheets(mDocumentURL);
if (NS_FAILED(rv)) return rv;
mCommand = aCommand;
rv = AddPrototypeSheets();
if (NS_FAILED(rv)) return rv;
{
// This scope restricts the lifetime of our reference to the
// loadgroup. Specifically, we don't want to have a reference
// to the load group on the stack when we call
// ResumeWalk().
nsCOMPtr<nsILoadGroup> loadgroup;
rv = nsComponentManager::CreateInstance(kLoadGroupCID,
nsnull,
NS_GET_IID(nsILoadGroup),
getter_AddRefs(loadgroup));
if (NS_FAILED(rv)) return rv;
// Create our own "document loader" that will fire the onload
// handlers when everything is finished. When this scope is
// closed, the loadgroup will be the only object with a
// reference to the loader.
nsCOMPtr<nsIStreamObserver> loader;
{
CachedChromeLoader* l = new CachedChromeLoader(this);
if (! l)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(l);
loader = do_QueryInterface(l, &rv);
NS_RELEASE(l);
if (NS_FAILED(rv)) return rv;
}
rv = loadgroup->Init(loader);
if (NS_FAILED(rv)) return rv;
// Even though we are only holding a weak reference to the
// load group, any channels that get added to the load group
// will acquire strong refs, keeping the load group alive
// until the last channel is complete.
mDocumentLoadGroup = getter_AddRefs(NS_GetWeakReference(loadgroup));
// Now create the delegates from the prototype
rv = PrepareToWalk();
if (NS_FAILED(rv)) return rv;
// Closing this scope will result in the placeholder channel
// created in PrepareToWalk() being the only reference to the
// load group.
}
rv = ResumeWalk();
return rv;
}
//----------------------------------------------------------------------
//
// nsIStreamLoadableDocument interface
@ -3030,8 +2984,8 @@ nsXULDocument::SetProperty(JSContext *aContext, jsval aID, jsval *aVp)
nsCOMPtr<nsIBaseWindow> webShellWin = do_QueryInterface(container);
if(!webShellWin) continue;
NS_ENSURE_SUCCESS(webShellWin->SetTitle(title.GetUnicode()),
PR_FALSE);
rv = webShellWin->SetTitle(title.GetUnicode());
if (NS_FAILED(rv)) return PR_FALSE;
}
}
else if (PL_strcmp("location", s) == 0) {
@ -3089,7 +3043,9 @@ nsXULDocument::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject)
// Make sure that we've got our script context owner; this
// assertion will fire if we've tried to get the script object
// before our scope has been set up.
NS_ENSURE_TRUE(mScriptGlobalObject, NS_ERROR_NOT_INITIALIZED);
NS_ASSERTION(mScriptGlobalObject != nsnull, "no script object");
if (! mScriptGlobalObject)
return NS_ERROR_NOT_INITIALIZED;
nsresult rv;
@ -3967,15 +3923,6 @@ nsXULDocument::PrepareToLoad(nsISupports* aContainer,
{
nsresult rv;
// Make sure we're not called from dead code (LoadFromStream)
NS_ENSURE_ARG_POINTER(aChannel);
// Get the document's URL
rv = aChannel->GetOriginalURI(getter_AddRefs(mDocumentURL));
if (NS_FAILED(rv)) return rv;
mDocumentTitle.Truncate();
// Get the document's principal
nsCOMPtr<nsISupports> owner;
rv = aChannel->GetOwner(getter_AddRefs(owner));
@ -3983,15 +3930,6 @@ nsXULDocument::PrepareToLoad(nsISupports* aContainer,
nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(owner);
// Set the document's load group
mDocumentLoadGroup = getter_AddRefs(NS_GetWeakReference(aLoadGroup));
// Prepare the document's style sheets
rv = PrepareStyleSheets(mDocumentURL);
if (NS_FAILED(rv)) return rv;
mCommand = aCommand;
return PrepareToLoadPrototype(mDocumentURL, aCommand, principal, aResult);
}
@ -4718,6 +4656,9 @@ nsXULDocument::ResumeWalk()
rv = ApplyPersistentAttributes();
if (NS_FAILED(rv)) return rv;
// Everything after this point we only want to do once we're
// certain that we've been embedded in a presentation shell.
#if defined(DEBUG_waterson) || defined(DEBUG_hyatt)
{
nsTime finish = PR_Now();
@ -4893,7 +4834,9 @@ nsXULDocument::ExecuteScript(JSObject* aScriptObject)
// Execute the precompiled script with the given version
nsresult rv;
NS_ENSURE_TRUE(mScriptGlobalObject, NS_ERROR_UNEXPECTED);
NS_ASSERTION(mScriptGlobalObject != nsnull, "no script global object");
if (! mScriptGlobalObject)
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIScriptContext> context;
rv = mScriptGlobalObject->GetContext(getter_AddRefs(context));
@ -5594,121 +5537,56 @@ nsXULDocument::IsChromeURI(nsIURI* aURI)
return PR_FALSE;
}
//----------------------------------------------------------------------
//
// CachedChromeLoader
// CachedChromeStreamListener
//
nsXULDocument::CachedChromeLoader::CachedChromeLoader(nsXULDocument* aDocument)
: mDocument(aDocument),
mLoading(PR_TRUE)
nsXULDocument::CachedChromeStreamListener::CachedChromeStreamListener(nsXULDocument* aDocument)
: mDocument(aDocument)
{
NS_INIT_REFCNT();
NS_ADDREF(aDocument);
NS_ADDREF(mDocument);
}
nsXULDocument::CachedChromeLoader::~CachedChromeLoader()
nsXULDocument::CachedChromeStreamListener::~CachedChromeStreamListener()
{
NS_RELEASE(mDocument);
}
NS_IMPL_ADDREF(nsXULDocument::CachedChromeLoader);
NS_IMPL_RELEASE(nsXULDocument::CachedChromeLoader);
NS_IMPL_ISUPPORTS2(nsXULDocument::CachedChromeStreamListener, nsIStreamObserver, nsIStreamListener);
NS_IMETHODIMP
nsXULDocument::CachedChromeLoader::QueryInterface(REFNSIID aIID, void** aResult)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(NS_GET_IID(nsIStreamObserver)) ||
aIID.Equals(NS_GET_IID(nsISupports))) {
*aResult = this;
NS_ADDREF(this);
return NS_OK;
}
else {
*aResult = nsnull;
return NS_NOINTERFACE;
}
}
NS_IMETHODIMP
nsXULDocument::CachedChromeLoader::OnStartRequest(nsIChannel* aChannel, nsISupports* aContext)
nsXULDocument::CachedChromeStreamListener::OnStartRequest(nsIChannel* aChannel, nsISupports* acontext)
{
return NS_OK;
}
NS_IMETHODIMP
nsXULDocument::CachedChromeLoader::OnStopRequest(nsIChannel* aChannel,
nsISupports* aContext,
nsresult aStatus,
const PRUnichar* aErrorMsg)
nsXULDocument::CachedChromeStreamListener::OnStopRequest(nsIChannel* aChannel,
nsISupports* aContext,
nsresult aStatus,
const PRUnichar* aErrorMsg)
{
// Not loading. Bail!
if (! mLoading)
return NS_OK;
nsCOMPtr<nsILoadGroup> group = do_QueryReferent(mDocument->mDocumentLoadGroup);
// No more load group. Bail!
if (! group)
return NS_OK;
nsresult rv;
PRUint32 count;
rv = group->GetActiveCount(&count);
rv = mDocument->PrepareToWalk();
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to prepare for walk");
if (NS_FAILED(rv)) return rv;
// Still loading. Bail!
if (count != 0)
return NS_OK;
mLoading = PR_FALSE;
for (PRInt32 i = mDocument->GetNumberOfShells() - 1; i >= 0; --i) {
// Walk from the pres shell down to the script context
// owner. We'll consider any failure along the way
// non-terminal, and will continue on to the other pres
// shells.
nsIPresShell* shell = mDocument->GetShellAt(i);
NS_ASSERTION(shell != nsnull, "null shell");
if (! shell)
continue;
// the pres shell has a pres context...
nsCOMPtr<nsIPresContext> presContext;
shell->GetPresContext(getter_AddRefs(presContext));
NS_ASSERTION(presContext != nsnull, "shell has no pres context");
if (! presContext)
continue;
// the pres context should have a content container (really the webshell)...
nsCOMPtr<nsISupports> container;
presContext->GetContainer(getter_AddRefs(container));
NS_ASSERTION(container != nsnull, "pres context has no container");
if (! container)
continue;
// the container should support GI to globalObject...
nsCOMPtr<nsIScriptGlobalObject> global(do_GetInterface(container, &rv));
if (NS_FAILED(rv))
continue;
// dispatch the 'load' event to the script global object
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_PAGE_LOAD;
rv = global->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
if (NS_FAILED(rv))
continue;
}
return NS_OK;
return mDocument->ResumeWalk();
}
NS_IMETHODIMP
nsXULDocument::CachedChromeStreamListener::OnDataAvailable(nsIChannel* aChannel,
nsISupports* aContext,
nsIInputStream* aInStr,
PRUint32 aSourceOffset,
PRUint32 aCount)
{
NS_NOTREACHED("CachedChromeStream doesn't receive data");
return NS_ERROR_UNEXPECTED;
}

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

@ -286,9 +286,6 @@ public:
NS_IMETHOD AddForwardReference(nsForwardReference* aRef);
NS_IMETHOD ResolveForwardReferences();
NS_IMETHOD CreateFromPrototype(const char* aCommand,
nsIXULPrototypeDocument* aPrototype);
// nsIStreamLoadableDocument interface
NS_IMETHOD LoadFromStream(nsIInputStream& xulStream,
nsISupports* aContainer,
@ -750,24 +747,21 @@ protected:
nsTime mLoadStart;
#endif
class CachedChromeLoader : public nsIStreamObserver
{
class CachedChromeStreamListener : public nsIStreamListener {
protected:
nsXULDocument* mDocument;
PRBool mLoading;
virtual ~CachedChromeStreamListener();
public:
CachedChromeLoader(nsXULDocument* aDocument);
virtual ~CachedChromeLoader();
CachedChromeStreamListener(nsXULDocument* aDocument);
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIStreamObserver interface
NS_DECL_NSISTREAMOBSERVER
NS_DECL_NSISTREAMLISTENER
};
friend class CachedChromeLoader;
friend class CachedChromeStreamListener;
};

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

@ -20,20 +20,227 @@
* Contributor(s):
*/
#include "nsChromeProtocolHandler.h"
#include "nsCOMPtr.h"
#include "nsCRT.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIIOService.h"
#include "nsChromeProtocolHandler.h"
#include "nsIChannel.h"
#include "nsIChromeRegistry.h"
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsIComponentManager.h"
#include "nsIIOService.h"
#include "nsILoadGroup.h"
#include "nsIScriptSecurityManager.h"
#include "nsIStreamListener.h"
#include "nsIServiceManager.h"
#include "nsIXULDocument.h"
#include "nsIXULPrototypeCache.h"
#include "nsIXULPrototypeDocument.h"
#include "nsRDFCID.h"
#include "nsXPIDLString.h"
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kChromeRegistryCID, NS_CHROMEREGISTRY_CID);
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
static NS_DEFINE_CID(kXULDocumentCID, NS_XULDOCUMENT_CID);
static NS_DEFINE_CID(kXULPrototypeCacheCID, NS_XULPROTOTYPECACHE_CID);
//----------------------------------------------------------------------
//
// A channel that's used for loading cached chrome documents.
//
class nsCachedChromeChannel : public nsIChannel
{
protected:
nsCachedChromeChannel(const char* aCommand, nsIURI* aURI);
virtual ~nsCachedChromeChannel();
const char* mCommand;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsILoadGroup> mLoadGroup;
public:
static nsresult
Create(const char* aCommand, nsIURI* aURI, nsIChannel** aResult);
NS_DECL_ISUPPORTS
// nsIRequest
NS_IMETHOD IsPending(PRBool *_retval) { *_retval = PR_TRUE; return NS_OK; }
NS_IMETHOD Cancel(void) { return NS_OK; }
NS_IMETHOD Suspend(void) { return NS_OK; }
NS_IMETHOD Resume(void) { return NS_OK; }
// nsIChannel
NS_DECL_NSICHANNEL
};
NS_IMPL_ADDREF(nsCachedChromeChannel);
NS_IMPL_RELEASE(nsCachedChromeChannel);
NS_IMPL_QUERY_INTERFACE2(nsCachedChromeChannel, nsIRequest, nsIChannel);
nsresult
nsCachedChromeChannel::Create(const char* aCommand, nsIURI* aURI, nsIChannel** aResult)
{
NS_PRECONDITION(aURI != nsnull, "null ptr");
if (! aURI)
return NS_ERROR_NULL_POINTER;
nsCachedChromeChannel* channel = new nsCachedChromeChannel(aCommand, aURI);
if (! channel)
return NS_ERROR_OUT_OF_MEMORY;
*aResult = channel;
NS_ADDREF(*aResult);
return NS_OK;
}
nsCachedChromeChannel::nsCachedChromeChannel(const char* aCommand, nsIURI* aURI)
: mCommand(aCommand),
mURI(aURI)
{
NS_INIT_REFCNT();
}
nsCachedChromeChannel::~nsCachedChromeChannel()
{
}
NS_IMETHODIMP
nsCachedChromeChannel::GetOriginalURI(nsIURI * *aOriginalURI)
{
*aOriginalURI = mURI;
NS_ADDREF(*aOriginalURI);
return NS_OK;
}
NS_IMETHODIMP
nsCachedChromeChannel::GetURI(nsIURI * *aURI)
{
*aURI = mURI;
NS_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP
nsCachedChromeChannel::OpenInputStream(PRUint32 startPosition, PRInt32 readCount, nsIInputStream **_retval)
{
NS_NOTREACHED("don't do that");
*_retval = nsnull;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream **_retval)
{
NS_NOTREACHED("don't do that");
*_retval = nsnull;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports *ctxt)
{
NS_NOTREACHED("don't do that");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount, nsISupports *ctxt, nsIStreamListener *listener)
{
if (listener) {
nsresult rv;
rv = listener->OnStartRequest(this, ctxt);
(void) listener->OnStopRequest(this, ctxt, rv, nsnull);
}
return NS_OK;
}
NS_IMETHODIMP
nsCachedChromeChannel::AsyncWrite(nsIInputStream *fromStream, PRUint32 startPosition, PRInt32 writeCount, nsISupports *ctxt, nsIStreamObserver *observer)
{
NS_NOTREACHED("don't do that");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
{
*aLoadAttributes = nsIChannel::LOAD_NORMAL;
return NS_OK;
}
NS_IMETHODIMP
nsCachedChromeChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
NS_NOTREACHED("don't do that");
return NS_OK;
}
NS_IMETHODIMP
nsCachedChromeChannel::GetContentType(char * *aContentType)
{
*aContentType = nsXPIDLCString::Copy("text/xul");
return *aContentType ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
NS_IMETHODIMP
nsCachedChromeChannel::GetContentLength(PRInt32 *aContentLength)
{
NS_NOTREACHED("don't do that");
*aContentLength = 0;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::GetOwner(nsISupports * *aOwner)
{
NS_NOTREACHED("don't do that");
*aOwner = nsnull;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::SetOwner(nsISupports * aOwner)
{
NS_NOTREACHED("don't do that");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::GetLoadGroup(nsILoadGroup * *aLoadGroup)
{
*aLoadGroup = mLoadGroup;
NS_IF_ADDREF(*aLoadGroup);
return NS_OK;
}
NS_IMETHODIMP
nsCachedChromeChannel::SetLoadGroup(nsILoadGroup * aLoadGroup)
{
mLoadGroup = aLoadGroup;
return NS_OK;
}
NS_IMETHODIMP
nsCachedChromeChannel::GetNotificationCallbacks(nsIInterfaceRequestor * *aNotificationCallbacks)
{
NS_NOTREACHED("don't do that");
*aNotificationCallbacks = nsnull;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCachedChromeChannel::SetNotificationCallbacks(nsIInterfaceRequestor * aNotificationCallbacks)
{
NS_NOTREACHED("don't do that");
return NS_ERROR_FAILURE;
}
////////////////////////////////////////////////////////////////////////////////
@ -124,53 +331,73 @@ nsChromeProtocolHandler::NewURI(const char *aSpec, nsIURI *aBaseURI,
}
NS_IMETHODIMP
nsChromeProtocolHandler::NewChannel(const char* verb, nsIURI* uri,
nsChromeProtocolHandler::NewChannel(const char* aVerb, nsIURI* aURI,
nsILoadGroup* aLoadGroup,
nsIInterfaceRequestor* notificationCallbacks,
nsLoadFlags loadAttributes,
nsIURI* originalURI,
nsIChannel* *result)
nsIInterfaceRequestor* aNotificationCallbacks,
nsLoadFlags aLoadAttributes,
nsIURI* aOriginalURI,
nsIChannel* *aResult)
{
nsresult rv;
NS_WITH_SERVICE(nsIChromeRegistry, reg, kChromeRegistryCID, &rv);
nsCOMPtr<nsIChannel> result;
// First check the prototype cache to see if we've already got the
// document in the cache.
NS_WITH_SERVICE(nsIXULPrototypeCache, cache, kXULPrototypeCacheCID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIURI> chromeURI;
rv = uri->Clone(getter_AddRefs(chromeURI)); // don't mangle the original
nsCOMPtr<nsIXULPrototypeDocument> proto;
rv = cache->GetPrototype(aURI, getter_AddRefs(proto));
if (NS_FAILED(rv)) return rv;
rv = reg->ConvertChromeURL(chromeURI);
if (NS_FAILED(rv)) return rv;
if (proto) {
// ...in which case, we'll create a dummy stream that'll just
// load the thing.
rv = nsCachedChromeChannel::Create(aVerb, aURI, getter_AddRefs(result));
if (NS_FAILED(rv)) return rv;
}
else {
// Miss. Resolve the chrome URL using the registry and do a
// normal necko load.
NS_WITH_SERVICE(nsIChromeRegistry, reg, kChromeRegistryCID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIURI> chromeURI;
rv = aURI->Clone(getter_AddRefs(chromeURI)); // don't mangle the original
if (NS_FAILED(rv)) return rv;
// now fetch the converted URI
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = reg->ConvertChromeURL(chromeURI);
if (NS_FAILED(rv)) return rv;
rv = serv->NewChannelFromURI(verb, chromeURI,
aLoadGroup,
notificationCallbacks,
loadAttributes,
originalURI ? originalURI : uri, result);
// now fetch the converted URI
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = serv->NewChannelFromURI(aVerb, chromeURI,
aLoadGroup,
aNotificationCallbacks,
aLoadAttributes,
aOriginalURI ? aOriginalURI : aURI,
getter_AddRefs(result));
if (NS_FAILED(rv)) return rv;
// Get a system principal for chrome and set the owner
// property of the result
NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager, NS_SCRIPTSECURITYMANAGER_PROGID, &rv);
if (NS_FAILED(rv)) return rv;
// Get a system principal for chrome and set the owner property
// of the result
if (NS_SUCCEEDED(rv)) {
nsresult rv2;
NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager,
NS_SCRIPTSECURITYMANAGER_PROGID, &rv2);
if (NS_FAILED(rv2))
return NS_ERROR_FAILURE;
nsCOMPtr<nsIPrincipal> principal;
if (NS_FAILED(securityManager->GetSystemPrincipal(getter_AddRefs(principal))))
{
return NS_ERROR_FAILURE;
}
rv = securityManager->GetSystemPrincipal(getter_AddRefs(principal));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISupports> owner = do_QueryInterface(principal);
(*result)->SetOwner(owner);
result->SetOwner(owner);
}
return rv;
*aResult = result;
NS_ADDREF(*aResult);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////

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

@ -101,13 +101,10 @@ public:
*/
NS_IMETHOD AddForwardReference(nsForwardReference* aForwardReference) = 0;
NS_IMETHOD ResolveForwardReferences() = 0;
/**
* Create a XUL document from a prototype
* Resolve the all of the document's forward references.
*/
NS_IMETHOD CreateFromPrototype(const char* aCommand,
nsIXULPrototypeDocument* aPrototype) = 0;
NS_IMETHOD ResolveForwardReferences() = 0;
};
// factory functions

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

@ -615,8 +615,6 @@ nsXULDocument::StartDocumentLoad(const char* aCommand,
nsISupports* aContainer,
nsIStreamListener **aDocListener)
{
nsresult rv;
#if defined(DEBUG_waterson) || defined(DEBUG_hyatt)
mLoadStart = PR_Now();
@ -627,22 +625,50 @@ nsXULDocument::StartDocumentLoad(const char* aCommand,
}
#endif
nsCOMPtr<nsIURI> url;
rv = aChannel->GetURI(getter_AddRefs(url));
nsresult rv;
mCommand = aCommand;
mDocumentLoadGroup = getter_AddRefs(NS_GetWeakReference(aLoadGroup));
mDocumentTitle.Truncate();
rv = aChannel->GetOriginalURI(getter_AddRefs(mDocumentURL));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIParser> parser;
rv = PrepareToLoad(aContainer, aCommand, aChannel, aLoadGroup, getter_AddRefs(parser));
rv = PrepareStyleSheets(mDocumentURL);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIStreamListener> listener = do_QueryInterface(parser, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "parser doesn't support nsIStreamListener");
// Look in the chrome cache: see if we've got this puppy loaded
// already.
nsCOMPtr<nsIXULPrototypeDocument> proto;
rv = gXULCache->GetPrototype(mDocumentURL, getter_AddRefs(proto));
if (NS_FAILED(rv)) return rv;
*aDocListener = listener;
if (proto) {
mMasterPrototype = mCurrentPrototype = proto;
rv = AddPrototypeSheets();
if (NS_FAILED(rv)) return rv;
*aDocListener = new CachedChromeStreamListener(this);
if (! *aDocListener)
return NS_ERROR_OUT_OF_MEMORY;
}
else {
nsCOMPtr<nsIParser> parser;
rv = PrepareToLoad(aContainer, aCommand, aChannel, aLoadGroup, getter_AddRefs(parser));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIStreamListener> listener = do_QueryInterface(parser, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "parser doesn't support nsIStreamListener");
if (NS_FAILED(rv)) return rv;
*aDocListener = listener;
parser->Parse(mDocumentURL);
}
NS_IF_ADDREF(*aDocListener);
parser->Parse(url);
return NS_OK;
}
@ -1229,8 +1255,7 @@ nsXULDocument::EndLoad()
rv = PrepareToWalk();
if (NS_FAILED(rv)) return rv;
rv = ResumeWalk();
return rv;
return ResumeWalk();
}
@ -1997,77 +2022,6 @@ nsXULDocument::ResolveForwardReferences()
}
NS_IMETHODIMP
nsXULDocument::CreateFromPrototype(const char* aCommand,
nsIXULPrototypeDocument* aPrototype)
{
nsresult rv;
mMasterPrototype = mCurrentPrototype = aPrototype;
rv = mCurrentPrototype->GetURI(getter_AddRefs(mDocumentURL));
if (NS_FAILED(rv)) return rv;
rv = PrepareStyleSheets(mDocumentURL);
if (NS_FAILED(rv)) return rv;
mCommand = aCommand;
rv = AddPrototypeSheets();
if (NS_FAILED(rv)) return rv;
{
// This scope restricts the lifetime of our reference to the
// loadgroup. Specifically, we don't want to have a reference
// to the load group on the stack when we call
// ResumeWalk().
nsCOMPtr<nsILoadGroup> loadgroup;
rv = nsComponentManager::CreateInstance(kLoadGroupCID,
nsnull,
NS_GET_IID(nsILoadGroup),
getter_AddRefs(loadgroup));
if (NS_FAILED(rv)) return rv;
// Create our own "document loader" that will fire the onload
// handlers when everything is finished. When this scope is
// closed, the loadgroup will be the only object with a
// reference to the loader.
nsCOMPtr<nsIStreamObserver> loader;
{
CachedChromeLoader* l = new CachedChromeLoader(this);
if (! l)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(l);
loader = do_QueryInterface(l, &rv);
NS_RELEASE(l);
if (NS_FAILED(rv)) return rv;
}
rv = loadgroup->Init(loader);
if (NS_FAILED(rv)) return rv;
// Even though we are only holding a weak reference to the
// load group, any channels that get added to the load group
// will acquire strong refs, keeping the load group alive
// until the last channel is complete.
mDocumentLoadGroup = getter_AddRefs(NS_GetWeakReference(loadgroup));
// Now create the delegates from the prototype
rv = PrepareToWalk();
if (NS_FAILED(rv)) return rv;
// Closing this scope will result in the placeholder channel
// created in PrepareToWalk() being the only reference to the
// load group.
}
rv = ResumeWalk();
return rv;
}
//----------------------------------------------------------------------
//
// nsIStreamLoadableDocument interface
@ -3030,8 +2984,8 @@ nsXULDocument::SetProperty(JSContext *aContext, jsval aID, jsval *aVp)
nsCOMPtr<nsIBaseWindow> webShellWin = do_QueryInterface(container);
if(!webShellWin) continue;
NS_ENSURE_SUCCESS(webShellWin->SetTitle(title.GetUnicode()),
PR_FALSE);
rv = webShellWin->SetTitle(title.GetUnicode());
if (NS_FAILED(rv)) return PR_FALSE;
}
}
else if (PL_strcmp("location", s) == 0) {
@ -3089,7 +3043,9 @@ nsXULDocument::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject)
// Make sure that we've got our script context owner; this
// assertion will fire if we've tried to get the script object
// before our scope has been set up.
NS_ENSURE_TRUE(mScriptGlobalObject, NS_ERROR_NOT_INITIALIZED);
NS_ASSERTION(mScriptGlobalObject != nsnull, "no script object");
if (! mScriptGlobalObject)
return NS_ERROR_NOT_INITIALIZED;
nsresult rv;
@ -3967,15 +3923,6 @@ nsXULDocument::PrepareToLoad(nsISupports* aContainer,
{
nsresult rv;
// Make sure we're not called from dead code (LoadFromStream)
NS_ENSURE_ARG_POINTER(aChannel);
// Get the document's URL
rv = aChannel->GetOriginalURI(getter_AddRefs(mDocumentURL));
if (NS_FAILED(rv)) return rv;
mDocumentTitle.Truncate();
// Get the document's principal
nsCOMPtr<nsISupports> owner;
rv = aChannel->GetOwner(getter_AddRefs(owner));
@ -3983,15 +3930,6 @@ nsXULDocument::PrepareToLoad(nsISupports* aContainer,
nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(owner);
// Set the document's load group
mDocumentLoadGroup = getter_AddRefs(NS_GetWeakReference(aLoadGroup));
// Prepare the document's style sheets
rv = PrepareStyleSheets(mDocumentURL);
if (NS_FAILED(rv)) return rv;
mCommand = aCommand;
return PrepareToLoadPrototype(mDocumentURL, aCommand, principal, aResult);
}
@ -4718,6 +4656,9 @@ nsXULDocument::ResumeWalk()
rv = ApplyPersistentAttributes();
if (NS_FAILED(rv)) return rv;
// Everything after this point we only want to do once we're
// certain that we've been embedded in a presentation shell.
#if defined(DEBUG_waterson) || defined(DEBUG_hyatt)
{
nsTime finish = PR_Now();
@ -4893,7 +4834,9 @@ nsXULDocument::ExecuteScript(JSObject* aScriptObject)
// Execute the precompiled script with the given version
nsresult rv;
NS_ENSURE_TRUE(mScriptGlobalObject, NS_ERROR_UNEXPECTED);
NS_ASSERTION(mScriptGlobalObject != nsnull, "no script global object");
if (! mScriptGlobalObject)
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIScriptContext> context;
rv = mScriptGlobalObject->GetContext(getter_AddRefs(context));
@ -5594,121 +5537,56 @@ nsXULDocument::IsChromeURI(nsIURI* aURI)
return PR_FALSE;
}
//----------------------------------------------------------------------
//
// CachedChromeLoader
// CachedChromeStreamListener
//
nsXULDocument::CachedChromeLoader::CachedChromeLoader(nsXULDocument* aDocument)
: mDocument(aDocument),
mLoading(PR_TRUE)
nsXULDocument::CachedChromeStreamListener::CachedChromeStreamListener(nsXULDocument* aDocument)
: mDocument(aDocument)
{
NS_INIT_REFCNT();
NS_ADDREF(aDocument);
NS_ADDREF(mDocument);
}
nsXULDocument::CachedChromeLoader::~CachedChromeLoader()
nsXULDocument::CachedChromeStreamListener::~CachedChromeStreamListener()
{
NS_RELEASE(mDocument);
}
NS_IMPL_ADDREF(nsXULDocument::CachedChromeLoader);
NS_IMPL_RELEASE(nsXULDocument::CachedChromeLoader);
NS_IMPL_ISUPPORTS2(nsXULDocument::CachedChromeStreamListener, nsIStreamObserver, nsIStreamListener);
NS_IMETHODIMP
nsXULDocument::CachedChromeLoader::QueryInterface(REFNSIID aIID, void** aResult)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(NS_GET_IID(nsIStreamObserver)) ||
aIID.Equals(NS_GET_IID(nsISupports))) {
*aResult = this;
NS_ADDREF(this);
return NS_OK;
}
else {
*aResult = nsnull;
return NS_NOINTERFACE;
}
}
NS_IMETHODIMP
nsXULDocument::CachedChromeLoader::OnStartRequest(nsIChannel* aChannel, nsISupports* aContext)
nsXULDocument::CachedChromeStreamListener::OnStartRequest(nsIChannel* aChannel, nsISupports* acontext)
{
return NS_OK;
}
NS_IMETHODIMP
nsXULDocument::CachedChromeLoader::OnStopRequest(nsIChannel* aChannel,
nsISupports* aContext,
nsresult aStatus,
const PRUnichar* aErrorMsg)
nsXULDocument::CachedChromeStreamListener::OnStopRequest(nsIChannel* aChannel,
nsISupports* aContext,
nsresult aStatus,
const PRUnichar* aErrorMsg)
{
// Not loading. Bail!
if (! mLoading)
return NS_OK;
nsCOMPtr<nsILoadGroup> group = do_QueryReferent(mDocument->mDocumentLoadGroup);
// No more load group. Bail!
if (! group)
return NS_OK;
nsresult rv;
PRUint32 count;
rv = group->GetActiveCount(&count);
rv = mDocument->PrepareToWalk();
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to prepare for walk");
if (NS_FAILED(rv)) return rv;
// Still loading. Bail!
if (count != 0)
return NS_OK;
mLoading = PR_FALSE;
for (PRInt32 i = mDocument->GetNumberOfShells() - 1; i >= 0; --i) {
// Walk from the pres shell down to the script context
// owner. We'll consider any failure along the way
// non-terminal, and will continue on to the other pres
// shells.
nsIPresShell* shell = mDocument->GetShellAt(i);
NS_ASSERTION(shell != nsnull, "null shell");
if (! shell)
continue;
// the pres shell has a pres context...
nsCOMPtr<nsIPresContext> presContext;
shell->GetPresContext(getter_AddRefs(presContext));
NS_ASSERTION(presContext != nsnull, "shell has no pres context");
if (! presContext)
continue;
// the pres context should have a content container (really the webshell)...
nsCOMPtr<nsISupports> container;
presContext->GetContainer(getter_AddRefs(container));
NS_ASSERTION(container != nsnull, "pres context has no container");
if (! container)
continue;
// the container should support GI to globalObject...
nsCOMPtr<nsIScriptGlobalObject> global(do_GetInterface(container, &rv));
if (NS_FAILED(rv))
continue;
// dispatch the 'load' event to the script global object
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_PAGE_LOAD;
rv = global->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
if (NS_FAILED(rv))
continue;
}
return NS_OK;
return mDocument->ResumeWalk();
}
NS_IMETHODIMP
nsXULDocument::CachedChromeStreamListener::OnDataAvailable(nsIChannel* aChannel,
nsISupports* aContext,
nsIInputStream* aInStr,
PRUint32 aSourceOffset,
PRUint32 aCount)
{
NS_NOTREACHED("CachedChromeStream doesn't receive data");
return NS_ERROR_UNEXPECTED;
}

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

@ -286,9 +286,6 @@ public:
NS_IMETHOD AddForwardReference(nsForwardReference* aRef);
NS_IMETHOD ResolveForwardReferences();
NS_IMETHOD CreateFromPrototype(const char* aCommand,
nsIXULPrototypeDocument* aPrototype);
// nsIStreamLoadableDocument interface
NS_IMETHOD LoadFromStream(nsIInputStream& xulStream,
nsISupports* aContainer,
@ -750,24 +747,21 @@ protected:
nsTime mLoadStart;
#endif
class CachedChromeLoader : public nsIStreamObserver
{
class CachedChromeStreamListener : public nsIStreamListener {
protected:
nsXULDocument* mDocument;
PRBool mLoading;
virtual ~CachedChromeStreamListener();
public:
CachedChromeLoader(nsXULDocument* aDocument);
virtual ~CachedChromeLoader();
CachedChromeStreamListener(nsXULDocument* aDocument);
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIStreamObserver interface
NS_DECL_NSISTREAMOBSERVER
NS_DECL_NSISTREAMLISTENER
};
friend class CachedChromeLoader;
friend class CachedChromeStreamListener;
};