Excise nsCachedChromeChannel fixing bug 206691 amongst others r=bsmedberg sr=bz
authorNeil Rashbrook <neil@parkwaycc.co.uk>
Thu, 29 Jan 2009 23:34:24 +0000
changeset 24420 908b22d8fefe1783fadfea6c476f665436f72410
parent 24419 f6b5ed8b38249ab949fae1578b118b3c00c003c9
child 24421 09abc221952080286a009556343cd15210c5e538
push idunknown
push userunknown
push dateunknown
reviewersbsmedberg, bz
bugs206691
milestone1.9.2a1pre
Excise nsCachedChromeChannel fixing bug 206691 amongst others r=bsmedberg sr=bz
chrome/src/nsChromeProtocolHandler.cpp
content/xul/document/src/Makefile.in
content/xul/document/src/nsXULDocument.cpp
--- a/chrome/src/nsChromeProtocolHandler.cpp
+++ b/chrome/src/nsChromeProtocolHandler.cpp
@@ -73,322 +73,16 @@
 #ifdef MOZ_XUL
 #include "nsIXULPrototypeCache.h"
 #endif
 
 //----------------------------------------------------------------------
 
 static NS_DEFINE_CID(kXULPrototypeCacheCID,      NS_XULPROTOTYPECACHE_CID);
 
-//----------------------------------------------------------------------
-//
-//  A channel that's used for loading cached chrome documents. Since a
-//  cached chrome document really doesn't have anything to do to load,
-//  this is just the puppeteer that pulls the webshell's strings at the
-//  right time.
-//
-//  Specifically, when AsyncOpen() is called, it adds the channel to
-//  the load group, and queues an asychronous event to fire the
-//  listener's OnStartRequest().
-//
-//  After triggering OnStartRequest(), it then queues another event
-//  which will fire the listener's OnStopRequest() and remove the
-//  channel from the load group.
-//
-//  Each is done asynchronously to allow the stack to unwind back to
-//  the main event loop. This avoids any weird re-entrancy that occurs
-//  if we try to immediately fire the On[Start|Stop]Request().
-//
-//  For logging information, NSPR_LOG_MODULES=nsCachedChromeChannel:5
-//
-#define LOG(args) PR_LOG(gLog, PR_LOG_DEBUG, args)
-
-#define NS_CACHEDCHROMECHANNEL_IMPL_IID \
-{ 0x281371d3, 0x6bc2, 0x499f, \
-  { 0x8d, 0x70, 0xcb, 0xfc, 0x01, 0x1b, 0xa0, 0x43 } }
-
-class nsCachedChromeChannel : public nsIChannel
-{
-protected:
-    ~nsCachedChromeChannel();
-
-    nsCOMPtr<nsIURI>            mURI;
-    nsCOMPtr<nsIURI>            mOriginalURI;
-    nsCOMPtr<nsILoadGroup>      mLoadGroup;
-    nsCOMPtr<nsIStreamListener> mListener;
-    nsCOMPtr<nsISupports>       mContext;
-    nsLoadFlags                 mLoadFlags;
-    nsCOMPtr<nsISupports>       mOwner;
-    nsresult                    mStatus;
-
-#ifdef PR_LOGGING
-    static PRLogModuleInfo* gLog;
-#endif
-
-    void HandleLoadEvent();
-
-public:
-    nsCachedChromeChannel(nsIURI* aURI);
-
-    NS_DECLARE_STATIC_IID_ACCESSOR(NS_CACHEDCHROMECHANNEL_IMPL_IID)
-
-    NS_DECL_ISUPPORTS
-
-    // nsIRequest
-    NS_IMETHOD GetName(nsACString &result) { return mURI->GetSpec(result); }
-    NS_IMETHOD IsPending(PRBool *_retval) { *_retval = (mListener != nsnull); return NS_OK; }
-    NS_IMETHOD GetStatus(nsresult *status) { *status = mStatus; return NS_OK; }
-    NS_IMETHOD Cancel(nsresult status)  { mStatus = status; return NS_OK; }
-    NS_IMETHOD Suspend(void) { return NS_OK; } // XXX technically wrong
-    NS_IMETHOD Resume(void)  { return NS_OK; } // XXX technically wrong
-    NS_IMETHOD GetLoadGroup(nsILoadGroup **);
-    NS_IMETHOD SetLoadGroup(nsILoadGroup *);
-    NS_IMETHOD GetLoadFlags(nsLoadFlags *);
-    NS_IMETHOD SetLoadFlags(nsLoadFlags);
-
-    // nsIChannel
-    NS_DECL_NSICHANNEL
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsCachedChromeChannel,
-                              NS_CACHEDCHROMECHANNEL_IMPL_IID)
-
-#ifdef PR_LOGGING
-PRLogModuleInfo* nsCachedChromeChannel::gLog;
-#endif
-
-NS_IMPL_ISUPPORTS3(nsCachedChromeChannel, nsIChannel, nsIRequest,
-                   nsCachedChromeChannel)
-
-nsCachedChromeChannel::nsCachedChromeChannel(nsIURI* aURI)
-    : mURI(aURI)
-    , mOriginalURI(aURI)
-    , mLoadFlags(nsIRequest::LOAD_NORMAL)
-    , mStatus(NS_OK)
-{
-#ifdef PR_LOGGING
-    if (! gLog)
-        gLog = PR_NewLogModule("nsCachedChromeChannel");
-#endif
-
-    LOG(("nsCachedChromeChannel[%p]: created", this));
-}
-
-
-nsCachedChromeChannel::~nsCachedChromeChannel()
-{
-    LOG(("nsCachedChromeChannel[%p]: destroyed", this));
-}
-
-
-NS_IMETHODIMP
-nsCachedChromeChannel::GetOriginalURI(nsIURI* *aOriginalURI)
-{
-    *aOriginalURI = mOriginalURI;
-    NS_ADDREF(*aOriginalURI);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::SetOriginalURI(nsIURI* aOriginalURI)
-{
-    NS_ENSURE_ARG_POINTER(aOriginalURI);
-    mOriginalURI = aOriginalURI;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::GetURI(nsIURI* *aURI)
-{
-    *aURI = mURI;
-    NS_ADDREF(*aURI);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::Open(nsIInputStream **_retval)
-{
-//    NS_NOTREACHED("don't do that");
-    *_retval = nsnull;
-    return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
-{
-    NS_ENSURE_ARG_POINTER(listener);
-
-    nsresult rv;
-
-    // Fire OnStartRequest and OnStopRequest, which will cause the XUL
-    // document to get embedded.
-    LOG(("nsCachedChromeChannel[%p]: posting load event for %p",
-        this, listener));
-
-    nsCOMPtr<nsIRunnable> event =
-        NS_NEW_RUNNABLE_METHOD(nsCachedChromeChannel, this, HandleLoadEvent);
-
-    // Queue an event to ourselves to let the stack unwind before
-    // calling OnStartRequest(). This allows embedding to occur
-    // before we fire OnStopRequest().
-    rv = NS_DispatchToCurrentThread(event);
-    if (NS_FAILED(rv))
-        return rv;
-
-    mContext  = ctxt;
-    mListener = listener;
-
-    if (mLoadGroup) {
-        LOG(("nsCachedChromeChannel[%p]: adding self to load group %p",
-            this, mLoadGroup.get()));
-
-        (void) mLoadGroup->AddRequest(this, nsnull);
-    }
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
-{
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
-{
-    *aLoadFlags = mLoadFlags;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
-{
-    mLoadFlags = aLoadFlags;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::GetOwner(nsISupports * *aOwner)
-{
-    *aOwner = mOwner;
-    NS_IF_ADDREF(*aOwner);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::SetOwner(nsISupports * aOwner)
-{
-    mOwner = aOwner;
-    return NS_OK;
-}
-
-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)
-{
-    *aNotificationCallbacks = nsnull;
-    return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::SetNotificationCallbacks(nsIInterfaceRequestor * aNotificationCallbacks)
-{
-    return NS_OK;	// ignored
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::GetContentType(nsACString &aContentType)
-{
-    aContentType.AssignLiteral("mozilla.application/cached-xul");
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::SetContentType(const nsACString &aContentType)
-{
-    // Do not allow the content-type to be changed.
-    NS_NOTREACHED("don't do that");
-    return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::GetContentCharset(nsACString &aContentCharset)
-{
-    aContentCharset.Truncate();
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::SetContentCharset(const nsACString &aContentCharset)
-{
-    // Do not allow the content charset to be changed.
-    NS_NOTREACHED("don't do that");
-    return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::GetContentLength(PRInt32 *aContentLength)
-{
-    NS_NOTREACHED("don't do that");
-    *aContentLength = 0;
-    return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsCachedChromeChannel::SetContentLength(PRInt32 aContentLength)
-{
-    NS_NOTREACHED("nsCachedChromeChannel::SetContentLength");
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-void
-nsCachedChromeChannel::HandleLoadEvent()
-{
-    // Fire the OnStartRequest() for the cached chrome channel, then
-    // trigger the OnStopRequest()...
-
-    // If the load has been cancelled, then just bail now. We won't
-    // send On[Start|Stop]Request().
-    if (NS_FAILED(mStatus))
-        return;
-
-    LOG(("nsCachedChromeChannel[%p]: firing OnStartRequest for %p",
-        this, mListener.get()));
-
-    mListener->OnStartRequest(this, mContext);
-
-    LOG(("nsCachedChromeChannel[%p]: firing OnStopRequest for %p",
-        this, mListener.get()));
-
-    mListener->OnStopRequest(this, mContext, mStatus);
-
-    if (mLoadGroup) {
-        LOG(("nsCachedChromeChannel[%p]: removing self from load group %p",
-            this, mLoadGroup.get()));
-        mLoadGroup->RemoveRequest(this, nsnull, mStatus);
-    }
-
-    mListener = nsnull;
-    mContext  = nsnull;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_THREADSAFE_ISUPPORTS2(nsChromeProtocolHandler,
                               nsIProtocolHandler,
                               nsISupportsWeakReference)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIProtocolHandler methods:
@@ -481,139 +175,114 @@ nsChromeProtocolHandler::NewChannel(nsIU
                 NS_ASSERTION(same, "Non-canonified chrome uri passed to nsChromeProtocolHandler::NewChannel!");
             }
         }
     }
 #endif
 
     nsCOMPtr<nsIChannel> result;
 
-#ifdef MOZ_XUL
-    // Check the prototype cache to see if we've already got the
-    // document in the cache.
-    nsCOMPtr<nsIXULPrototypeCache> cache
-        (do_GetService(kXULPrototypeCacheCID));
-
-    PRBool isCached = PR_FALSE;
-    if (cache)
-        isCached = cache->IsCached(aURI);
-    else
-        NS_WARNING("Unable to obtain the XUL prototype cache!");
+    if (!nsChromeRegistry::gChromeRegistry) {
+        // We don't actually want this ref, we just want the service to
+        // initialize if it hasn't already.
+        nsCOMPtr<nsIChromeRegistry> reg(do_GetService(NS_CHROMEREGISTRY_CONTRACTID));
+        NS_ENSURE_TRUE(nsChromeRegistry::gChromeRegistry, NS_ERROR_FAILURE);
+    }
 
-    // Same comment as nsXULDocument::StartDocumentLoad and
-    // nsXULDocument::ResumeWalk
-    // - Ben Goodger
-    //
-    // We don't abort on failure here because there are too many valid
-    // cases that can return failure, and the null-ness of |proto| is enough
-    // to trigger the fail-safe parse-from-disk solution. Example failure cases
-    // (for reference) include:
-    //
-    // NS_ERROR_NOT_AVAILABLE: the URI cannot be found in the FastLoad cache, 
-    //                         parse from disk
-    // other: the FastLoad cache file, XUL.mfl, could not be found, probably
-    //        due to being accessed before a profile has been selected (e.g.
-    //        loading chrome for the profile manager itself). This must be 
-    //        parsed from disk. 
+    nsCOMPtr<nsIURI> resolvedURI;
+    rv = nsChromeRegistry::gChromeRegistry->ConvertChromeURL(aURI, getter_AddRefs(resolvedURI));
+    if (NS_FAILED(rv)) {
+#ifdef DEBUG
+        nsCAutoString spec;
+        aURI->GetSpec(spec);
+        printf("Couldn't convert chrome URL: %s\n", spec.get());
+#endif
+        return rv;
+    }
+
+    nsCOMPtr<nsIIOService> ioServ(do_GetIOService(&rv));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = ioServ->NewChannelFromURI(resolvedURI, getter_AddRefs(result));
+    if (NS_FAILED(rv)) return rv;
 
-    if (isCached) {
-        // ...in which case, we'll create a dummy stream that'll just
-        // load the thing.
-        result = new nsCachedChromeChannel(aURI);
-        if (! result)
-            return NS_ERROR_OUT_OF_MEMORY;
-    }
-    else {
-#endif // MOZ_XUL
-        // Miss. Resolve the chrome URL using the registry and do a
-        // normal necko load.
-        //nsXPIDLCString oldSpec;
-        //aURI->GetSpec(getter_Copies(oldSpec));
-        //printf("*************************** %s\n", (const char*)oldSpec);
+#ifdef DEBUG
+    nsCOMPtr<nsIFileChannel> fileChan(do_QueryInterface(result));
+    if (fileChan) {
+        nsCOMPtr<nsIFile> file;
+        fileChan->GetFile(getter_AddRefs(file));
 
-        if (!nsChromeRegistry::gChromeRegistry) {
-            // We don't actually want this ref, we just want the service to
-            // initialize if it hasn't already.
-            nsCOMPtr<nsIChromeRegistry> reg (do_GetService(NS_CHROMEREGISTRY_CONTRACTID));
+        PRBool exists = PR_FALSE;
+        file->Exists(&exists);
+        if (!exists) {
+            nsCAutoString path;
+            file->GetNativePath(path);
+            printf("Chrome file doesn't exist: %s\n", path.get());
         }
-
-        NS_ENSURE_TRUE(nsChromeRegistry::gChromeRegistry, NS_ERROR_FAILURE);
+    }
+#endif
 
-        nsCOMPtr<nsIURI> resolvedURI;
-        rv = nsChromeRegistry::gChromeRegistry->ConvertChromeURL(aURI, getter_AddRefs(resolvedURI));
-        if (NS_FAILED(rv)) {
-#ifdef DEBUG
-            nsCAutoString spec;
-            aURI->GetSpec(spec);
-            printf("Couldn't convert chrome URL: %s\n", spec.get());
-#endif
-            return rv;
-        }
+    // Make sure that the channel remembers where it was
+    // originally loaded from.
+    rv = result->SetOriginalURI(aURI);
+    if (NS_FAILED(rv)) return rv;
 
-        nsCOMPtr<nsIIOService> ioServ (do_GetIOService(&rv));
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        rv = ioServ->NewChannelFromURI(resolvedURI, getter_AddRefs(result));
+    // Get a system principal for content files and set the owner
+    // property of the result
+    nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
+    nsCAutoString path;
+    rv = url->GetPath(path);
+    if (StringBeginsWith(path, NS_LITERAL_CSTRING("/content/")))
+    {
+        nsCOMPtr<nsIScriptSecurityManager> securityManager =
+                 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
         if (NS_FAILED(rv)) return rv;
 
-        // Make sure that the channel remembers where it was
-        // originally loaded from.
-        rv = result->SetOriginalURI(aURI);
+        nsCOMPtr<nsIPrincipal> principal;
+        rv = securityManager->GetSystemPrincipal(getter_AddRefs(principal));
         if (NS_FAILED(rv)) return rv;
 
-        // Get a system principal for content files and set the owner
-        // property of the result
-        nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
-        nsCAutoString path;
-        rv = url->GetPath(path);
-        if (StringBeginsWith(path, NS_LITERAL_CSTRING("/content/")))
-        {
-            nsCOMPtr<nsIScriptSecurityManager> securityManager =
-                     do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
-            if (NS_FAILED(rv)) return rv;
-
-            nsCOMPtr<nsIPrincipal> principal;
-            rv = securityManager->GetSystemPrincipal(getter_AddRefs(principal));
-            if (NS_FAILED(rv)) return rv;
-
-            nsCOMPtr<nsISupports> owner = do_QueryInterface(principal);
-            result->SetOwner(owner);
-        }
+        nsCOMPtr<nsISupports> owner = do_QueryInterface(principal);
+        result->SetOwner(owner);
+    }
 
 #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<nsIFastLoadService> fastLoadServ(do_GetFastLoadService());
-        if (fastLoadServ) {
-            nsCOMPtr<nsIObjectOutputStream> objectOutput;
-            fastLoadServ->GetOutputStream(getter_AddRefs(objectOutput));
-            if (objectOutput) {
-                nsCOMPtr<nsIFile> file;
+    // 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<nsIFastLoadService> fastLoadServ(do_GetFastLoadService());
+    if (fastLoadServ) {
+        nsCOMPtr<nsIObjectOutputStream> objectOutput;
+        fastLoadServ->GetOutputStream(getter_AddRefs(objectOutput));
+        if (objectOutput) {
+            nsCOMPtr<nsIFile> file;
 
-                nsCOMPtr<nsIURI> uri;
-                result->GetURI(getter_AddRefs(uri));
-                uri = NS_GetInnermostURI(uri);
+            nsCOMPtr<nsIURI> 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<nsIFileURL> fileURL(do_QueryInterface(uri));
-                if (fileURL)
-                    fileURL->GetFile(getter_AddRefs(file));
+            // Here we have a URL of the form resource:/chrome/A.jar
+            // or file:/some/path/to/A.jar.
+            nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(uri));
+            if (fileURL)
+                fileURL->GetFile(getter_AddRefs(file));
 
-                if (file) {
-                    rv = fastLoadServ->AddDependency(file);
-                    if (NS_FAILED(rv))
-                        cache->AbortFastLoads();
+            if (file) {
+                rv = fastLoadServ->AddDependency(file);
+                if (NS_FAILED(rv)) {
+                   nsCOMPtr<nsIXULPrototypeCache> cache
+                       (do_GetService(kXULPrototypeCacheCID));
+                   if (cache)
+                       cache->AbortFastLoads();
                 }
             }
         }
     }
 #endif
 
     *aResult = result;
     NS_ADDREF(*aResult);
--- a/content/xul/document/src/Makefile.in
+++ b/content/xul/document/src/Makefile.in
@@ -66,16 +66,17 @@ REQUIRES	= xpcom \
 		  htmlparser \
 		  docshell \
 		  pref \
 		  xultmpl \
 		  webshell \
 		  unicharutil \
 		  appshell \
 		  util \
+		  imglib2 \
 		  $(NULL)
 
 CPPSRCS		= nsXULControllers.cpp
 
 ifdef MOZ_XUL
 CPPSRCS		+= \
 		nsXULCommandDispatcher.cpp \
 		nsXULContentSink.cpp \
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -120,16 +120,17 @@
 #include "nsContentErrors.h"
 #include "nsIObserverService.h"
 #include "nsNodeUtils.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIXULWindow.h"
 #include "nsXULPopupManager.h"
 #include "nsCCUncollectableMarker.h"
+#include "ImageErrors.h"
 
 //----------------------------------------------------------------------
 //
 // CIDs
 //
 
 static NS_DEFINE_CID(kParserCID,                 NS_PARSER_CID);
 
@@ -4490,17 +4491,18 @@ nsXULDocument::CachedChromeStreamListene
 
 NS_IMPL_ISUPPORTS2(nsXULDocument::CachedChromeStreamListener,
                    nsIRequestObserver, nsIStreamListener)
 
 NS_IMETHODIMP
 nsXULDocument::CachedChromeStreamListener::OnStartRequest(nsIRequest *request,
                                                           nsISupports* acontext)
 {
-    return NS_OK;
+    // XXX need a proper cancel-but-run-onload-handlers return code (bug 475344)
+    return NS_IMAGELIB_ERROR_LOAD_ABORTED;
 }
 
 
 NS_IMETHODIMP
 nsXULDocument::CachedChromeStreamListener::OnStopRequest(nsIRequest *request,
                                                          nsISupports* aContext,
                                                          nsresult aStatus)
 {