зеркало из https://github.com/mozilla/gecko-dev.git
Bug 18392. Use XUL document cache for retrieving master document.
This commit is contained in:
Родитель
e634ed06f2
Коммит
82fb1998b7
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче