Backout 231cce402e46, 383b6031c417, 8a518d6c8b60 & 4f55f76e34ee (bug 813438) for bustage
authorEd Morley <emorley@mozilla.com>
Thu, 22 Nov 2012 17:49:58 +0000
changeset 114019 607fa073ae8e0ca04d6d0d0f5df9a24b84c90a13
parent 114018 fde699842ede0b9fccfcb22c15e6a4cc6be98c37
child 114020 db7d2a9d2ce3087c4e88f6b972cf52794270ddca
push id23896
push usercpearce@mozilla.com
push dateFri, 23 Nov 2012 02:23:35 +0000
treeherdermozilla-central@c27455415eac [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs813438
milestone20.0a1
backs out231cce402e46461e85851512e7bbe6a09df79e42
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backout 231cce402e46, 383b6031c417, 8a518d6c8b60 & 4f55f76e34ee (bug 813438) for bustage
netwerk/base/public/nsNetUtil.h
netwerk/base/src/nsBaseChannel.cpp
netwerk/base/src/nsIOService.cpp
netwerk/base/src/nsIOService.h
netwerk/build/nsNetCID.h
netwerk/build/nsNetModule.cpp
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/streamconv/converters/nsUnknownDecoder.cpp
netwerk/streamconv/converters/nsUnknownDecoder.h
toolkit/components/places/AsyncFaviconHelpers.cpp
xpcom/glue/nsCategoryCache.h
--- a/netwerk/base/public/nsNetUtil.h
+++ b/netwerk/base/public/nsNetUtil.h
@@ -74,18 +74,16 @@
 #include "nsISocketProvider.h"
 #include "nsIRedirectChannelRegistrar.h"
 #include "nsIMIMEHeaderParam.h"
 #include "nsILoadContext.h"
 #include "mozilla/Services.h"
 #include "nsIPrivateBrowsingChannel.h"
 #include "mozIApplicationClearPrivateDataParams.h"
 #include "nsIOfflineCacheUpdate.h"
-#include "nsIContentSniffer.h"
-#include "nsCategoryCache.h"
 
 #include <limits>
 
 #ifdef MOZILLA_INTERNAL_API
 
 inline already_AddRefed<nsIIOService>
 do_GetIOService(nsresult* error = 0)
 {
@@ -2151,51 +2149,9 @@ NS_GenerateHostPort(const nsCString& hos
         hostLine.Assign(host);
     if (port != -1) {
         hostLine.Append(':');
         hostLine.AppendInt(port);
     }
     return NS_OK;
 }
 
-/**
- * Sniff the content type for a given request or a given buffer.
- *
- * aSnifferType can be either NS_CONTENT_SNIFFER_CATEGORY or
- * NS_DATA_SNIFFER_CATEGORY.  The function returns the sniffed content type
- * in the aSniffedType argument.  This argument will not be modified if the
- * content type could not be sniffed.
- */
-inline void
-NS_SniffContent(const char* aSnifferType, nsIRequest* aRequest,
-                const uint8_t* aData, uint32_t aLength,
-                nsACString& aSniffedType)
-{
-  typedef nsCategoryCache<nsIContentSniffer> ContentSnifferCache;
-  extern NS_HIDDEN_(ContentSnifferCache*) gNetSniffers;
-  extern NS_HIDDEN_(ContentSnifferCache*) gDataSniffers;
-  ContentSnifferCache* cache = nullptr;
-  if (!strcmp(aSnifferType, NS_CONTENT_SNIFFER_CATEGORY)) {
-    if (!gNetSniffers) {
-      gNetSniffers = new ContentSnifferCache(NS_CONTENT_SNIFFER_CATEGORY);
-    }
-    cache = gNetSniffers;
-  } else if (!strcmp(aSnifferType, NS_DATA_SNIFFER_CATEGORY)) {
-    if (!gDataSniffers) {
-      gDataSniffers = new ContentSnifferCache(NS_DATA_SNIFFER_CATEGORY);
-    }
-    cache = gDataSniffers;
-  } else {
-    // Invalid content sniffer type was requested
-    MOZ_ASSERT(false);
-    return;
-  }
-
-  const nsCOMArray<nsIContentSniffer>& sniffers = cache->GetEntries();
-  for (int32_t i = 0; i < sniffers.Count(); ++i) {
-    nsresult rv = sniffers[i]->GetMIMETypeFromContent(aRequest, aData, aLength, aSniffedType);
-    if (NS_SUCCEEDED(rv) && !aSniffedType.IsEmpty()) {
-      break;
-    }
-  }
-}
-
 #endif // !nsNetUtil_h__
--- a/netwerk/base/src/nsBaseChannel.cpp
+++ b/netwerk/base/src/nsBaseChannel.cpp
@@ -8,16 +8,17 @@
 #include "nsURLHelper.h"
 #include "nsNetUtil.h"
 #include "nsMimeTypes.h"
 #include "nsIOService.h"
 #include "nsIHttpEventSink.h"
 #include "nsIHttpChannel.h"
 #include "nsIChannelEventSink.h"
 #include "nsIStreamConverterService.h"
+#include "nsIContentSniffer.h"
 #include "nsChannelClassifier.h"
 #include "nsAsyncRedirectVerifyHelper.h"
 
 static PLDHashOperator
 CopyProperties(const nsAString &key, nsIVariant *data, void *closure)
 {
   nsIWritablePropertyBag *bag =
       static_cast<nsIWritablePropertyBag *>(closure);
@@ -667,20 +668,27 @@ nsBaseChannel::GetInterface(const nsIID 
 //-----------------------------------------------------------------------------
 // nsBaseChannel::nsIRequestObserver
 
 static void
 CallTypeSniffers(void *aClosure, const uint8_t *aData, uint32_t aCount)
 {
   nsIChannel *chan = static_cast<nsIChannel*>(aClosure);
 
-  nsAutoCString newType;
-  NS_SniffContent(NS_CONTENT_SNIFFER_CATEGORY, chan, aData, aCount, newType);
-  if (!newType.IsEmpty()) {
-    chan->SetContentType(newType);
+  const nsCOMArray<nsIContentSniffer>& sniffers =
+    gIOService->GetContentSniffers();
+  uint32_t length = sniffers.Count();
+  for (uint32_t i = 0; i < length; ++i) {
+    nsAutoCString newType;
+    nsresult rv =
+      sniffers[i]->GetMIMETypeFromContent(chan, aData, aCount, newType);
+    if (NS_SUCCEEDED(rv) && !newType.IsEmpty()) {
+      chan->SetContentType(newType);
+      break;
+    }
   }
 }
 
 static void
 CallUnknownTypeSniffer(void *aClosure, const uint8_t *aData, uint32_t aCount)
 {
   nsIChannel *chan = static_cast<nsIChannel*>(aClosure);
 
@@ -706,17 +714,18 @@ nsBaseChannel::OnStartRequest(nsIRequest
             ((mLoadFlags & LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN) &&
             mContentType.EqualsLiteral(APPLICATION_OCTET_STREAM));
 
   if (NS_SUCCEEDED(mStatus) && shouldSniff) {
     mPump->PeekStream(CallUnknownTypeSniffer, static_cast<nsIChannel*>(this));
   }
 
   // Now, the general type sniffers. Skip this if we have none.
-  if (mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS)
+  if ((mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) &&
+      gIOService->GetContentSniffers().Count() != 0)
     mPump->PeekStream(CallTypeSniffers, static_cast<nsIChannel*>(this));
 
   SUSPEND_PUMP_FOR_SCOPE();
 
   if (mListener) // null in case of redirect
       return mListener->OnStartRequest(this, mListenerContext);
   return NS_OK;
 }
--- a/netwerk/base/src/nsIOService.cpp
+++ b/netwerk/base/src/nsIOService.cpp
@@ -148,16 +148,17 @@ nsIOService::nsIOService()
     : mOffline(true)
     , mOfflineForProfileChange(false)
     , mManageOfflineStatus(false)
     , mSettingOffline(false)
     , mSetOfflineValue(false)
     , mShutdown(false)
     , mNetworkLinkServiceInitialized(false)
     , mChannelEventSinks(NS_CHANNEL_EVENT_SINK_CATEGORY)
+    , mContentSniffers(NS_CONTENT_SNIFFER_CATEGORY)
     , mAutoDialEnabled(false)
 {
 }
 
 nsresult
 nsIOService::Init()
 {
     nsresult rv;
--- a/netwerk/base/src/nsIOService.h
+++ b/netwerk/base/src/nsIOService.h
@@ -66,16 +66,21 @@ public:
                                 nsIProtocolHandler* *hdlrResult);
 
     // Called by channels before a redirect happens. This notifies the global
     // redirect observers.
     nsresult AsyncOnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan,
                                     uint32_t flags,
                                     nsAsyncRedirectVerifyHelper *helper);
 
+    // Gets the array of registered content sniffers
+    const nsCOMArray<nsIContentSniffer>& GetContentSniffers() {
+      return mContentSniffers.GetEntries();
+    }
+
     bool IsOffline() { return mOffline; }
     bool IsLinkUp();
 
     bool IsComingOnline() const {
       return mOffline && mSettingOffline && !mSetOfflineValue;
     }
 
 private:
@@ -124,16 +129,17 @@ private:
     nsCOMPtr<nsINetworkLinkService>      mNetworkLinkService;
     bool                                 mNetworkLinkServiceInitialized;
 
     // Cached protocol handlers
     nsWeakPtr                            mWeakHandler[NS_N(gScheme)];
 
     // cached categories
     nsCategoryCache<nsIChannelEventSink> mChannelEventSinks;
+    nsCategoryCache<nsIContentSniffer>   mContentSniffers;
 
     nsTArray<int32_t>                    mRestrictedPortList;
 
     bool                                 mAutoDialEnabled;
 public:
     // Used for all default buffer sizes that necko allocates.
     static uint32_t   gDefaultSegmentSize;
     static uint32_t   gDefaultSegmentCount;
--- a/netwerk/build/nsNetCID.h
+++ b/netwerk/build/nsNetCID.h
@@ -1023,19 +1023,13 @@
  * override.
  *
  * Not all channels may implement content sniffing. See also
  * nsIChannel::LOAD_CALL_CONTENT_SNIFFERS.
  */
 #define NS_CONTENT_SNIFFER_CATEGORY "net-content-sniffers"
 
 /**
- * Services in this category can sniff content that is not necessarily loaded
- * from the network, and they won't be told about each load.
- */
-#define NS_DATA_SNIFFER_CATEGORY "content-sniffing-services"
-
-/**
  * Must implement nsINSSErrorsService.
  */
 #define NS_NSS_ERRORS_SERVICE_CONTRACTID "@mozilla.org/nss_errors_service;1"
 
 #endif // nsNetCID_h__
--- a/netwerk/build/nsNetModule.cpp
+++ b/netwerk/build/nsNetModule.cpp
@@ -29,33 +29,27 @@
 #include "nsDiskCacheDeviceSQL.h"
 #include "nsApplicationCache.h"
 #include "nsApplicationCacheService.h"
 #include "nsMimeTypes.h"
 #include "nsNetStrings.h"
 #include "nsDNSPrefetch.h"
 #include "nsAboutProtocolHandler.h"
 #include "nsXULAppAPI.h"
-#include "nsCategoryCache.h"
-#include "nsIContentSniffer.h"
 
 #include "nsNetCID.h"
 
 #if defined(XP_MACOSX)
 #if !defined(__LP64__)
 #define BUILD_APPLEFILE_DECODER 1
 #endif
 #else
 #define BUILD_BINHEX_DECODER 1
 #endif
 
-typedef nsCategoryCache<nsIContentSniffer> ContentSnifferCache;
-NS_HIDDEN_(ContentSnifferCache*) gNetSniffers = nullptr;
-NS_HIDDEN_(ContentSnifferCache*) gDataSniffers = nullptr;
-
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "nsIOService.h"
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIOService, nsIOService::GetInstance)
 
 #include "nsDNSService2.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDNSService, Init)
   
@@ -644,21 +638,16 @@ static void nsNetShutdown()
     
     // Release DNS service reference.
     nsDNSPrefetch::Shutdown();
 
 #ifdef NECKO_PROTOCOL_websocket
     // Release the Websocket Admission Manager
     mozilla::net::WebSocketChannel::Shutdown();
 #endif // NECKO_PROTOCOL_websocket
-
-    delete gNetSniffers;
-    gNetSniffers = nullptr;
-    delete gDataSniffers;
-    gDataSniffers = nullptr;
 }
 
 NS_DEFINE_NAMED_CID(NS_IOSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_STREAMTRANSPORTSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_SOCKETTRANSPORTSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_SERVERSOCKET_CID);
 NS_DEFINE_NAMED_CID(NS_SOCKETPROVIDERSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_DNSSERVICE_CID);
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -861,30 +861,38 @@ nsHttpChannel::SetupTransaction()
 
 // NOTE: This function duplicates code from nsBaseChannel. This will go away
 // once HTTP uses nsBaseChannel (part of bug 312760)
 static void
 CallTypeSniffers(void *aClosure, const uint8_t *aData, uint32_t aCount)
 {
   nsIChannel *chan = static_cast<nsIChannel*>(aClosure);
 
-  nsAutoCString newType;
-  NS_SniffContent(NS_CONTENT_SNIFFER_CATEGORY, chan, aData, aCount, newType);
-  if (!newType.IsEmpty()) {
-    chan->SetContentType(newType);
+  const nsCOMArray<nsIContentSniffer>& sniffers =
+    gIOService->GetContentSniffers();
+  uint32_t length = sniffers.Count();
+  for (uint32_t i = 0; i < length; ++i) {
+    nsAutoCString newType;
+    nsresult rv =
+      sniffers[i]->GetMIMETypeFromContent(chan, aData, aCount, newType);
+    if (NS_SUCCEEDED(rv) && !newType.IsEmpty()) {
+      chan->SetContentType(newType);
+      break;
+    }
   }
 }
 
 nsresult
 nsHttpChannel::CallOnStartRequest()
 {
     mTracingEnabled = false;
 
     // Allow consumers to override our content type
-    if (mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) {
+    if ((mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) &&
+        gIOService->GetContentSniffers().Count() != 0) {
         // NOTE: We can have both a txn pump and a cache pump when the cache
         // content is partial. In that case, we need to read from the cache,
         // because that's the one that has the initial contents. If that fails
         // then give the transaction pump a shot.
 
         nsIChannel* thisChannel = static_cast<nsIChannel*>(this);
 
         bool typeSniffersCalled = false;
--- a/netwerk/streamconv/converters/nsUnknownDecoder.cpp
+++ b/netwerk/streamconv/converters/nsUnknownDecoder.cpp
@@ -12,25 +12,25 @@
 #include "nsIOutputStream.h"
 #include "nsMimeTypes.h"
 #include "netCore.h"
 #include "nsXPIDLString.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsICategoryManager.h"
 #include "nsISupportsPrimitives.h"
+#include "nsIContentSniffer.h"
 
 #include "nsCRT.h"
 
 #include "nsIMIMEService.h"
 
 #include "nsIViewSourceChannel.h"
 #include "nsIHttpChannel.h"
 #include "nsNetCID.h"
-#include "nsNetUtil.h"
 
 
 #define MAX_BUFFER_SIZE 512
 
 nsUnknownDecoder::nsUnknownDecoder()
   : mBuffer(nullptr)
   , mBufferLen(0)
   , mRequireHTMLsuffix(false)
@@ -329,19 +329,19 @@ void nsUnknownDecoder::DetermineContentT
       if ((this->*(sSnifferEntries[i].mContentTypeSniffer))(aRequest)) {
         NS_ASSERTION(!mContentType.IsEmpty(), 
                      "Content type should be known by now.");
         return;
       }        
     }
   }
 
-  NS_SniffContent(NS_DATA_SNIFFER_CATEGORY, aRequest,
-                  (const uint8_t*)mBuffer, mBufferLen, mContentType);
-  if (!mContentType.IsEmpty()) {
+  if (TryContentSniffers(aRequest)) {
+    NS_ASSERTION(!mContentType.IsEmpty(), 
+                 "Content type should be known by now.");
     return;
   }
 
   if (SniffForHTML(aRequest)) {
     NS_ASSERTION(!mContentType.IsEmpty(), 
                  "Content type should be known by now.");
     return;
   }
@@ -354,16 +354,59 @@ void nsUnknownDecoder::DetermineContentT
     return;
   }
   
   LastDitchSniff(aRequest);
   NS_ASSERTION(!mContentType.IsEmpty(), 
                "Content type should be known by now.");
 }
 
+bool nsUnknownDecoder::TryContentSniffers(nsIRequest* aRequest)
+{
+  // Enumerate content sniffers
+  nsCOMPtr<nsICategoryManager> catMan(do_GetService("@mozilla.org/categorymanager;1"));
+  if (!catMan) {
+    return false;
+  }
+
+  nsCOMPtr<nsISimpleEnumerator> sniffers;
+  catMan->EnumerateCategory("content-sniffing-services", getter_AddRefs(sniffers));
+  if (!sniffers) {
+    return false;
+  }
+
+  bool hasMore;
+  while (NS_SUCCEEDED(sniffers->HasMoreElements(&hasMore)) && hasMore) {
+    nsCOMPtr<nsISupports> elem;
+    sniffers->GetNext(getter_AddRefs(elem));
+    NS_ASSERTION(elem, "No element even though hasMore returned true!?");
+
+    nsCOMPtr<nsISupportsCString> sniffer_id(do_QueryInterface(elem));
+    NS_ASSERTION(sniffer_id, "element is no nsISupportsCString!?");
+    nsAutoCString contractid;
+    nsresult rv = sniffer_id->GetData(contractid);
+    if (NS_FAILED(rv)) {
+      continue;
+    }
+
+    nsCOMPtr<nsIContentSniffer> sniffer(do_GetService(contractid.get()));
+    if (!sniffer) {
+      continue;
+    }
+
+    rv = sniffer->GetMIMETypeFromContent(aRequest, (const uint8_t*)mBuffer,
+                                         mBufferLen, mContentType);
+    if (NS_SUCCEEDED(rv)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 bool nsUnknownDecoder::SniffForHTML(nsIRequest* aRequest)
 {
   /*
    * To prevent a possible attack, we will not consider this to be
    * html content if it comes from the local file system and our prefs
    * are set right
    */
   if (!AllowSniffing(aRequest)) {
--- a/netwerk/streamconv/converters/nsUnknownDecoder.h
+++ b/netwerk/streamconv/converters/nsUnknownDecoder.h
@@ -55,16 +55,17 @@ protected:
   // dangerous types (eg HTML) is ok for this request.  We can disable
   // sniffing for local files if needed using this.  Just a security
   // precation thingy... who knows when we suddenly need to flip this
   // pref?
   bool AllowSniffing(nsIRequest* aRequest);
   
   // Various sniffer functions.  Returning true means that a type
   // was determined; false means no luck.
+  bool TryContentSniffers(nsIRequest* aRequest);
   bool SniffForHTML(nsIRequest* aRequest);
   bool SniffForXML(nsIRequest* aRequest);
 
   // SniffURI guesses at the content type based on the URI (typically
   // using the extentsion)
   bool SniffURI(nsIRequest* aRequest);
 
   // LastDitchSniff guesses at text/plain vs. application/octet-stream
--- a/toolkit/components/places/AsyncFaviconHelpers.cpp
+++ b/toolkit/components/places/AsyncFaviconHelpers.cpp
@@ -1,32 +1,35 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AsyncFaviconHelpers.h"
 
+#include "nsIContentSniffer.h"
 #include "nsICacheService.h"
 #include "nsICacheVisitor.h"
 #include "nsICachingChannel.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 
 #include "nsNavHistory.h"
 #include "nsFaviconService.h"
 #include "mozilla/storage.h"
 #include "nsNetUtil.h"
 #include "nsPrintfCString.h"
 #include "nsStreamUtils.h"
 #include "nsIPrivateBrowsingChannel.h"
 #if !(defined(MOZ_PER_WINDOW_PRIVATE_BROWSING)) && defined(DEBUG)
 #include "nsIPrivateBrowsingService.h"
 #endif
 
+#define CONTENT_SNIFFING_SERVICES "content-sniffing-services"
+
 using namespace mozilla::places;
 using namespace mozilla::storage;
 
 namespace mozilla {
 namespace places {
 
 namespace {
 
@@ -281,16 +284,65 @@ FetchIconURL(nsRefPtr<Database>& aDB,
     rv = stmt->GetUTF8String(0, aIconSpec);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 /**
+ * Tries to guess the mimeType from icon data.
+ *
+ * @param aRequest
+ *        The network request object.
+ * @param aData
+ *        Data for this icon.
+ * @param _mimeType
+ *        The guessed mime-type or empty string if a valid one can't be found.
+ */
+nsresult
+SniffMimeTypeForIconData(nsIRequest* aRequest,
+                         const nsCString& aData,
+                         nsCString& _mimeType)
+{
+  NS_PRECONDITION(NS_IsMainThread(),
+                  "This should be called on the main thread");
+
+  nsCOMPtr<nsICategoryManager> categoryManager =
+    do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
+  NS_ENSURE_TRUE(categoryManager, NS_ERROR_OUT_OF_MEMORY);
+  nsCOMPtr<nsISimpleEnumerator> sniffers;
+  nsresult rv = categoryManager->EnumerateCategory(CONTENT_SNIFFING_SERVICES,
+                                                   getter_AddRefs(sniffers));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  bool hasMore = false;
+  while (_mimeType.IsEmpty() &&
+         NS_SUCCEEDED(sniffers->HasMoreElements(&hasMore)) &&
+         hasMore) {
+    nsCOMPtr<nsISupports> snifferCIDSupports;
+    rv = sniffers->GetNext(getter_AddRefs(snifferCIDSupports));
+    NS_ENSURE_SUCCESS(rv, rv);
+    nsCOMPtr<nsISupportsCString> snifferCIDSupportsCString =
+      do_QueryInterface(snifferCIDSupports);
+    NS_ENSURE_STATE(snifferCIDSupports);
+    nsAutoCString snifferCID;
+    rv = snifferCIDSupportsCString->GetData(snifferCID);
+    NS_ENSURE_SUCCESS(rv, rv);
+    nsCOMPtr<nsIContentSniffer> sniffer = do_GetService(snifferCID.get());
+    NS_ENSURE_STATE(sniffer);
+
+     // Ignore errors: we'll try the next sniffer.
+    (void)sniffer->GetMIMETypeFromContent(aRequest, TO_INTBUFFER(aData),
+                                          aData.Length(), _mimeType);
+  }
+  return NS_OK;
+}
+
+/**
  * Tries to compute the expiration time for a icon from the channel.
  *
  * @param aChannel
  *        The network channel used to fetch the icon.
  * @return a valid expiration value for the fetched icon.
  */
 PRTime
 GetExpirationTimeFromChannel(nsIChannel* aChannel)
@@ -639,31 +691,28 @@ AsyncFetchAndSetIconFromNetwork::OnStopR
                                                nsISupports* aContext,
                                                nsresult aStatusCode)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsFaviconService* favicons = nsFaviconService::GetFaviconService();
   NS_ENSURE_STATE(favicons);
 
-  nsresult rv;
-
   // If fetching the icon failed, add it to the failed cache.
   if (NS_FAILED(aStatusCode) || mIcon.data.Length() == 0) {
     nsCOMPtr<nsIURI> iconURI;
-    rv = NS_NewURI(getter_AddRefs(iconURI), mIcon.spec);
+    nsresult rv = NS_NewURI(getter_AddRefs(iconURI), mIcon.spec);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = favicons->AddFailedFavicon(iconURI);
     NS_ENSURE_SUCCESS(rv, rv);
     return NS_OK;
   }
 
-  NS_SniffContent(NS_DATA_SNIFFER_CATEGORY, aRequest,
-                  TO_INTBUFFER(mIcon.data), mIcon.data.Length(),
-                  mIcon.mimeType);
+  nsresult rv = SniffMimeTypeForIconData(aRequest, mIcon.data, mIcon.mimeType);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   // If the icon does not have a valid MIME type, add it to the failed cache.
   if (mIcon.mimeType.IsEmpty()) {
     nsCOMPtr<nsIURI> iconURI;
     rv = NS_NewURI(getter_AddRefs(iconURI), mIcon.spec);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = favicons->AddFailedFavicon(iconURI);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/xpcom/glue/nsCategoryCache.h
+++ b/xpcom/glue/nsCategoryCache.h
@@ -54,17 +54,17 @@ class NS_COM_GLUE nsCategoryObserver MOZ
 /**
  * This is a helper class that caches services that are registered in a certain
  * category. The intended usage is that a service stores a variable of type
  * nsCategoryCache<nsIFoo> in a member variable, where nsIFoo is the interface
  * that these services should implement. The constructor of this class should
  * then get the name of the category.
  */
 template<class T>
-class nsCategoryCache MOZ_FINAL : protected nsCategoryListener {
+class nsCategoryCache : protected nsCategoryListener {
   public:
     explicit nsCategoryCache(const char* aCategory);
     ~nsCategoryCache() { if (mObserver) mObserver->ListenerDied(); }
 
     const nsCOMArray<T>& GetEntries() {
       // Lazy initialization, so that services in this category can't
       // cause reentrant getService (bug 386376)
       if (!mObserver)