Bug 541496 part 5: use the string-taking API for sync sheet loads. r=bzbarsky
authorZack Weinberg <zackw@panix.com>
Wed, 18 May 2011 21:22:59 -0400
changeset 69704 303c10f7ae5c2830f191726aeeec66175e3cbb18
parent 69703 ca4404b5a114865ddb69884ca615329ef0150a00
child 69705 d9d8cade34332662dfb5c6ec5fa0bc6062575f14
push idunknown
push userunknown
push dateunknown
reviewersbzbarsky
bugs541496
milestone6.0a1
Bug 541496 part 5: use the string-taking API for sync sheet loads. r=bzbarsky
content/base/src/nsSyncLoadService.cpp
layout/style/Loader.cpp
--- a/content/base/src/nsSyncLoadService.cpp
+++ b/content/base/src/nsSyncLoadService.cpp
@@ -470,33 +470,37 @@ nsSyncLoadService::PushSyncStreamToListe
         rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), aIn,
                                        chunkSize);
         NS_ENSURE_SUCCESS(rv, rv);
 
         aIn = bufferedStream;
     }
 
     // Load
-    aListener->OnStartRequest(aChannel, nsnull);
-    PRUint32 sourceOffset = 0;
-    while (1) {
-        PRUint32 readCount = 0;
-        rv = aIn->Available(&readCount);
-        if (NS_FAILED(rv) || !readCount) {
-            if (rv == NS_BASE_STREAM_CLOSED) {
-                // End of file, but not an error
-                rv = NS_OK;
+    rv = aListener->OnStartRequest(aChannel, nsnull);
+    if (NS_SUCCEEDED(rv)) {
+        PRUint32 sourceOffset = 0;
+        while (1) {
+            PRUint32 readCount = 0;
+            rv = aIn->Available(&readCount);
+            if (NS_FAILED(rv) || !readCount) {
+                if (rv == NS_BASE_STREAM_CLOSED) {
+                    // End of file, but not an error
+                    rv = NS_OK;
+                }
+                break;
             }
-            break;
+
+            rv = aListener->OnDataAvailable(aChannel, nsnull, aIn,
+                                            sourceOffset, readCount);
+            if (NS_FAILED(rv)) {
+                break;
+            }
+            sourceOffset += readCount;
         }
-
-        rv = aListener->OnDataAvailable(aChannel, nsnull, aIn, sourceOffset,
-                                        readCount);
-        if (NS_FAILED(rv)) {
-            break;
-        }
-
-        sourceOffset += readCount;
+    }
+    if (NS_FAILED(rv)) {
+        aChannel->Cancel(rv);
     }
     aListener->OnStopRequest(aChannel, nsnull, rv);
-    
+
     return rv;
 }
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -46,28 +46,26 @@
  * 04/20/2000       IBM Corp.      OS/2 VisualAge build.
  */
 
 /* loading of CSS style sheets using the network APIs */
 
 #include "mozilla/css/Loader.h"
 #include "nsIRunnable.h"
 #include "nsIUnicharStreamLoader.h"
+#include "nsSyncLoadService.h"
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "nsString.h"
 #include "nsIContent.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMWindow.h"
 #include "nsIDocument.h"
 #include "nsIDOMNSDocumentStyle.h"
-#include "nsIUnicharInputStream.h"
-#include "nsIConverterInputStream.h"
 #include "nsICharsetAlias.h"
-#include "nsUnicharUtils.h"
 #include "nsHashtable.h"
 #include "nsIURI.h"
 #include "nsIServiceManager.h"
 #include "nsNetUtil.h"
 #include "nsContentUtils.h"
 #include "nsCRT.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsContentPolicyUtils.h"
@@ -799,17 +797,21 @@ SheetLoadData::OnStreamComplete(nsIUnich
     mLoader->SheetComplete(this, NS_ERROR_UNEXPECTED);
     return NS_OK;
   }
 
   nsCOMPtr<nsIPrincipal> principal;
   nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
   result = NS_ERROR_NOT_AVAILABLE;
   if (secMan) {  // Could be null if we already shut down
-    result = secMan->GetChannelPrincipal(channel, getter_AddRefs(principal));
+    if (mUseSystemPrincipal) {
+      result = secMan->GetSystemPrincipal(getter_AddRefs(principal));
+    } else {
+      result = secMan->GetChannelPrincipal(channel, getter_AddRefs(principal));
+    }
   }
 
   if (NS_FAILED(result)) {
     LOG_WARN(("  Couldn't get principal"));
     mLoader->SheetComplete(this, result);
     return NS_OK;
   }
 
@@ -890,17 +892,19 @@ SheetLoadData::OnStreamComplete(nsIUnich
     }
   }
 
   // Enough to set the URIs on mSheet, since any sibling datas we have share
   // the same mInner as mSheet and will thus get the same URI.
   mSheet->SetURIs(channelURI, originalURI, channelURI);
 
   PRBool completed;
-  return mLoader->ParseSheet(aBuffer, this, completed);
+  result = mLoader->ParseSheet(aBuffer, this, completed);
+  NS_ASSERTION(completed || !mSyncLoad, "sync load did not complete");
+  return result;
 }
 
 #ifdef MOZ_XUL
 static PRBool IsChromeURI(nsIURI* aURI)
 {
   NS_ASSERTION(aURI, "Have to pass in a URI");
   PRBool isChrome = PR_FALSE;
   aURI->SchemeIs("chrome", &isChrome);
@@ -1335,78 +1339,53 @@ Loader::LoadSheet(SheetLoadData* aLoadDa
   }
 
   if (aLoadData->mSyncLoad) {
     LOG(("  Synchronous load"));
     NS_ASSERTION(!aLoadData->mObserver, "Observer for a sync load?");
     NS_ASSERTION(aSheetState == eSheetNeedsParser,
                  "Sync loads can't reuse existing async loads");
 
+    // Create a nsIUnicharStreamLoader instance to which we will feed
+    // the data from the sync load.  Do this before creating the
+    // channel to make error recovery simpler.
+    nsCOMPtr<nsIUnicharStreamLoader> streamLoader;
+    rv = NS_NewUnicharStreamLoader(getter_AddRefs(streamLoader), aLoadData);
+    if (NS_FAILED(rv)) {
+      LOG_ERROR(("  Failed to create stream loader for sync load"));
+      SheetComplete(aLoadData, rv);
+      return rv;
+    }
+
     // Just load it
     nsCOMPtr<nsIInputStream> stream;
     nsCOMPtr<nsIChannel> channel;
     rv = NS_OpenURI(getter_AddRefs(stream), aLoadData->mURI, nsnull,
                     nsnull, nsnull, nsIRequest::LOAD_NORMAL,
                     getter_AddRefs(channel));
     if (NS_FAILED(rv)) {
       LOG_ERROR(("  Failed to open URI synchronously"));
       SheetComplete(aLoadData, rv);
       return rv;
     }
 
     NS_ASSERTION(channel, "NS_OpenURI lied?");
 
-    // Get the principal for this sheet
-    nsCOMPtr<nsIPrincipal> principal;
-    if (aLoadData->mUseSystemPrincipal) {
-      rv = nsContentUtils::GetSecurityManager()->
-        GetSystemPrincipal(getter_AddRefs(principal));
-    } else {
-      rv = nsContentUtils::GetSecurityManager()->
-        GetChannelPrincipal(channel, getter_AddRefs(principal));
-    }
-
-    if (NS_FAILED(rv)) {
-      LOG_ERROR(("  Failed to get a principal for the sheet"));
-      SheetComplete(aLoadData, rv);
-      return rv;
-    }
-
-    aLoadData->mSheet->SetPrincipal(principal);
-
-    nsCOMPtr<nsIConverterInputStream> converterStream =
-      do_CreateInstance("@mozilla.org/intl/converter-input-stream;1", &rv);
+    // Force UA sheets to be UTF-8.
+    // XXX this is only necessary because the default in
+    // SheetLoadData::OnDetermineCharset is wrong (bug 521039).
+    channel->SetContentCharset(NS_LITERAL_CSTRING("UTF-8"));
 
-    if (NS_FAILED(rv)) {
-      LOG_ERROR(("  Failed to create converter stream"));
-      SheetComplete(aLoadData, rv);
-      return rv;
-    }
-
-    // This forces UA sheets to be UTF-8.  We should really look for
-    // @charset rules here via ReadSegments on the raw stream...
-
-    // 8192 is a nice magic number that happens to be what a lot of
-    // other things use for buffer sizes.
-    rv = converterStream->Init(stream, "UTF-8",
-                               8192,
-                               nsIConverterInputStream::
-                                    DEFAULT_REPLACEMENT_CHARACTER);
-
-    if (NS_FAILED(rv)) {
-      LOG_ERROR(("  Failed to initialize converter stream"));
-      SheetComplete(aLoadData, rv);
-      return rv;
-    }
-
-    PRBool completed;
-    rv = ParseSheet(static_cast<nsIUnicharInputStream&>(*converterStream),
-                    aLoadData, completed);
-    NS_ASSERTION(completed, "sync load did not complete");
-    return rv;
+    // Manually feed the streamloader the contents of the stream we
+    // got from NS_OpenURI.  This will call back into OnStreamComplete
+    // and thence to ParseSheet.  Regardless of whether this fails,
+    // SheetComplete has been called.
+    return nsSyncLoadService::PushSyncStreamToListener(stream,
+                                                       streamLoader,
+                                                       channel);
   }
 
   SheetLoadData* existingData = nsnull;
 
   URIAndPrincipalHashKey key(aLoadData->mURI, aLoadData->mLoaderPrincipal);
   if (aSheetState == eSheetLoading) {
     mLoadingDatas.Get(&key, &existingData);
     NS_ASSERTION(existingData, "CreateSheet lied about the state");