diff --git a/chrome/src/nsChromeProtocolHandler.cpp b/chrome/src/nsChromeProtocolHandler.cpp index 7df3fa80603..16c36a7a0ea 100644 --- a/chrome/src/nsChromeProtocolHandler.cpp +++ b/chrome/src/nsChromeProtocolHandler.cpp @@ -245,11 +245,45 @@ nsChromeProtocolHandler::NewChannel(nsIURI* aURI, result->SetOwner(owner); } - // XXX Removed dependency-tracking code from here, because we're not - // tracking them anyways (with fastload we checked only in DEBUG - // and with startupcache not at all), but this is where we would start - // if we need to re-add. - // See bug 531886, bug 533038. +#ifdef MOZ_XUL + // Track FastLoad file dependencies. + // + // This is harder than it ought to be! While an nsResChannel "is-a" + // nsIFileChannel, an nsJARChannel is not. Once you unravel the jar: + // URI, you may have a resource: URL -- but without a channel for it, + // you can't get the URI that it yields through substitution! + // + // XXXbe fix nsResChannel.cpp to move the substitution code into a new + // nsResURL class? + nsCOMPtr fastLoadServ(do_GetFastLoadService()); + if (fastLoadServ) { + nsCOMPtr objectOutput; + fastLoadServ->GetOutputStream(getter_AddRefs(objectOutput)); + if (objectOutput) { + nsCOMPtr file; + + nsCOMPtr uri; + result->GetURI(getter_AddRefs(uri)); + uri = NS_GetInnermostURI(uri); + + // Here we have a URL of the form resource:/chrome/A.jar + // or file:/some/path/to/A.jar. + nsCOMPtr fileURL(do_QueryInterface(uri)); + if (fileURL) + fileURL->GetFile(getter_AddRefs(file)); + + if (file) { + rv = fastLoadServ->AddDependency(file); + if (NS_FAILED(rv)) { + nsCOMPtr cache + (do_GetService(kXULPrototypeCacheCID)); + if (cache) + cache->AbortFastLoads(); + } + } + } + } +#endif *aResult = result; NS_ADDREF(*aResult); diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index ec1a355be13..e80efb5e1fd 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -84,6 +84,7 @@ #include "nsIEventListenerManager.h" #include "nsEventStateManager.h" #include "nsFocusManager.h" +#include "nsIFastLoadService.h" #include "nsHTMLStyleSheet.h" #include "nsINameSpaceManager.h" #include "nsIObjectInputStream.h" @@ -2687,9 +2688,9 @@ nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream, if (script->mScriptObject.mObject) { // This may return NS_OK without muxing script->mSrcURI's - // data into the cache file, in the case where that + // data into the FastLoad file, in the case where that // muxed document is already there (written by a prior - // session, or by an earlier cache episode during this + // session, or by an earlier FastLoad episode during this // session). rv |= script->SerializeOutOfLine(aStream, aGlobal); } @@ -2819,8 +2820,8 @@ nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream, // Oh dear. Something failed during the deserialization. // We don't know what. But likely consequences of failed - // deserializations included calls to |AbortCaching| which - // shuts down the cache and closes our streams. + // deserializations included calls to |AbortFastLoads| which + // shuts down the FastLoadService and closes our streams. // If that happens, next time through this loop, we die a messy // death. So, let's just fail now, and propagate that failure // upward so that the ChromeProtocolHandler knows it can't use @@ -2960,23 +2961,24 @@ nsresult nsXULPrototypeScript::SerializeOutOfLine(nsIObjectOutputStream* aStream, nsIScriptGlobalObject* aGlobal) { - nsresult rv = NS_ERROR_NOT_IMPLEMENTED; - - PRBool isChrome = PR_FALSE; - if (NS_FAILED(mSrcURI->SchemeIs("chrome", &isChrome)) || !isChrome) - // Don't cache scripts that don't come from chrome uris. - return rv; - nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance(); if (!cache) return NS_ERROR_OUT_OF_MEMORY; NS_ASSERTION(cache->IsEnabled(), - "writing to the cache file, but the XUL cache is off?"); - PRBool exists; - cache->HasData(mSrcURI, &exists); - - + "writing to the FastLoad file, but the XUL cache is off?"); + + nsIFastLoadService* fastLoadService = cache->GetFastLoadService(); + if (!fastLoadService) + return NS_ERROR_NOT_AVAILABLE; + + nsCAutoString urispec; + nsresult rv = mSrcURI->GetAsciiSpec(urispec); + if (NS_FAILED(rv)) + return rv; + + PRBool exists = PR_FALSE; + fastLoadService->HasMuxedDocument(urispec.get(), &exists); /* return will be NS_OK from GetAsciiSpec. * that makes no sense. * nor does returning NS_OK from HasMuxedDocument. @@ -2985,15 +2987,34 @@ nsXULPrototypeScript::SerializeOutOfLine(nsIObjectOutputStream* aStream, if (exists) return NS_OK; - nsCOMPtr oos; - rv = cache->GetOutputStream(mSrcURI, getter_AddRefs(oos)); - NS_ENSURE_SUCCESS(rv, rv); - - rv |= Serialize(oos, aGlobal, nsnull); - rv |= cache->FinishOutputStream(mSrcURI); + // Allow callers to pass null for aStream, meaning + // "use the FastLoad service's default output stream." + // See nsXULDocument.cpp for one use of this. + nsCOMPtr objectOutput = aStream; + if (! objectOutput) { + fastLoadService->GetOutputStream(getter_AddRefs(objectOutput)); + if (! objectOutput) + return NS_ERROR_NOT_AVAILABLE; + } + + rv = fastLoadService-> + StartMuxedDocument(mSrcURI, urispec.get(), + nsIFastLoadService::NS_FASTLOAD_WRITE); + NS_ASSERTION(rv != NS_ERROR_NOT_AVAILABLE, "reading FastLoad?!"); + + nsCOMPtr oldURI; + rv |= fastLoadService->SelectMuxedDocument(mSrcURI, getter_AddRefs(oldURI)); + rv |= Serialize(objectOutput, aGlobal, nsnull); + rv |= fastLoadService->EndMuxedDocument(mSrcURI); + + if (oldURI) { + nsCOMPtr tempURI; + rv |= fastLoadService-> + SelectMuxedDocument(oldURI, getter_AddRefs(tempURI)); + } if (NS_FAILED(rv)) - cache->AbortCaching(); + cache->AbortFastLoads(); return rv; } @@ -3034,24 +3055,33 @@ nsresult nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput, nsIScriptGlobalObject* aGlobal) { - // Keep track of failure via rv, so we can - // AbortCaching if things look bad. + // Keep track of FastLoad failure via rv, so we can + // AbortFastLoads if things look bad. nsresult rv = NS_OK; + nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance(); - + nsIFastLoadService* fastLoadService = cache->GetFastLoadService(); + + // Allow callers to pass null for aInput, meaning + // "use the FastLoad service's default input stream." + // See nsXULContentSink.cpp for one use of this. nsCOMPtr objectInput = aInput; - if (cache) { + if (! objectInput && fastLoadService) + fastLoadService->GetInputStream(getter_AddRefs(objectInput)); + + if (objectInput) { PRBool useXULCache = PR_TRUE; if (mSrcURI) { // NB: we must check the XUL script cache early, to avoid - // multiple deserialization attempts for a given script. - // Note that nsXULDocument::LoadScript + // multiple deserialization attempts for a given script, which + // would exhaust the multiplexed stream containing the singly + // serialized script. Note that nsXULDocument::LoadScript // checks the XUL script cache too, in order to handle the // serialization case. // // We need do this only for