Backout 231cce402e46, 383b6031c417, 8a518d6c8b60 & 4f55f76e34ee (bug 813438) for bustage

This commit is contained in:
Ed Morley 2012-11-22 17:49:58 +00:00
Родитель 1590899437
Коммит 5aec97aa38
11 изменённых файлов: 138 добавлений и 82 удалений

Просмотреть файл

@ -79,8 +79,6 @@
#include "nsIPrivateBrowsingChannel.h" #include "nsIPrivateBrowsingChannel.h"
#include "mozIApplicationClearPrivateDataParams.h" #include "mozIApplicationClearPrivateDataParams.h"
#include "nsIOfflineCacheUpdate.h" #include "nsIOfflineCacheUpdate.h"
#include "nsIContentSniffer.h"
#include "nsCategoryCache.h"
#include <limits> #include <limits>
@ -2156,46 +2154,4 @@ NS_GenerateHostPort(const nsCString& host, int32_t port,
return NS_OK; 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__ #endif // !nsNetUtil_h__

Просмотреть файл

@ -13,6 +13,7 @@
#include "nsIHttpChannel.h" #include "nsIHttpChannel.h"
#include "nsIChannelEventSink.h" #include "nsIChannelEventSink.h"
#include "nsIStreamConverterService.h" #include "nsIStreamConverterService.h"
#include "nsIContentSniffer.h"
#include "nsChannelClassifier.h" #include "nsChannelClassifier.h"
#include "nsAsyncRedirectVerifyHelper.h" #include "nsAsyncRedirectVerifyHelper.h"
@ -672,10 +673,17 @@ CallTypeSniffers(void *aClosure, const uint8_t *aData, uint32_t aCount)
{ {
nsIChannel *chan = static_cast<nsIChannel*>(aClosure); nsIChannel *chan = static_cast<nsIChannel*>(aClosure);
const nsCOMArray<nsIContentSniffer>& sniffers =
gIOService->GetContentSniffers();
uint32_t length = sniffers.Count();
for (uint32_t i = 0; i < length; ++i) {
nsAutoCString newType; nsAutoCString newType;
NS_SniffContent(NS_CONTENT_SNIFFER_CATEGORY, chan, aData, aCount, newType); nsresult rv =
if (!newType.IsEmpty()) { sniffers[i]->GetMIMETypeFromContent(chan, aData, aCount, newType);
if (NS_SUCCEEDED(rv) && !newType.IsEmpty()) {
chan->SetContentType(newType); chan->SetContentType(newType);
break;
}
} }
} }
@ -711,7 +719,8 @@ nsBaseChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
} }
// Now, the general type sniffers. Skip this if we have none. // 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)); mPump->PeekStream(CallTypeSniffers, static_cast<nsIChannel*>(this));
SUSPEND_PUMP_FOR_SCOPE(); SUSPEND_PUMP_FOR_SCOPE();

Просмотреть файл

@ -153,6 +153,7 @@ nsIOService::nsIOService()
, mShutdown(false) , mShutdown(false)
, mNetworkLinkServiceInitialized(false) , mNetworkLinkServiceInitialized(false)
, mChannelEventSinks(NS_CHANNEL_EVENT_SINK_CATEGORY) , mChannelEventSinks(NS_CHANNEL_EVENT_SINK_CATEGORY)
, mContentSniffers(NS_CONTENT_SNIFFER_CATEGORY)
, mAutoDialEnabled(false) , mAutoDialEnabled(false)
{ {
} }

Просмотреть файл

@ -71,6 +71,11 @@ public:
uint32_t flags, uint32_t flags,
nsAsyncRedirectVerifyHelper *helper); nsAsyncRedirectVerifyHelper *helper);
// Gets the array of registered content sniffers
const nsCOMArray<nsIContentSniffer>& GetContentSniffers() {
return mContentSniffers.GetEntries();
}
bool IsOffline() { return mOffline; } bool IsOffline() { return mOffline; }
bool IsLinkUp(); bool IsLinkUp();
@ -129,6 +134,7 @@ private:
// cached categories // cached categories
nsCategoryCache<nsIChannelEventSink> mChannelEventSinks; nsCategoryCache<nsIChannelEventSink> mChannelEventSinks;
nsCategoryCache<nsIContentSniffer> mContentSniffers;
nsTArray<int32_t> mRestrictedPortList; nsTArray<int32_t> mRestrictedPortList;

Просмотреть файл

@ -1027,12 +1027,6 @@
*/ */
#define NS_CONTENT_SNIFFER_CATEGORY "net-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. * Must implement nsINSSErrorsService.
*/ */

Просмотреть файл

@ -34,8 +34,6 @@
#include "nsDNSPrefetch.h" #include "nsDNSPrefetch.h"
#include "nsAboutProtocolHandler.h" #include "nsAboutProtocolHandler.h"
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
#include "nsCategoryCache.h"
#include "nsIContentSniffer.h"
#include "nsNetCID.h" #include "nsNetCID.h"
@ -47,10 +45,6 @@
#define BUILD_BINHEX_DECODER 1 #define BUILD_BINHEX_DECODER 1
#endif #endif
typedef nsCategoryCache<nsIContentSniffer> ContentSnifferCache;
NS_HIDDEN_(ContentSnifferCache*) gNetSniffers = nullptr;
NS_HIDDEN_(ContentSnifferCache*) gDataSniffers = nullptr;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include "nsIOService.h" #include "nsIOService.h"
@ -649,11 +643,6 @@ static void nsNetShutdown()
// Release the Websocket Admission Manager // Release the Websocket Admission Manager
mozilla::net::WebSocketChannel::Shutdown(); mozilla::net::WebSocketChannel::Shutdown();
#endif // NECKO_PROTOCOL_websocket #endif // NECKO_PROTOCOL_websocket
delete gNetSniffers;
gNetSniffers = nullptr;
delete gDataSniffers;
gDataSniffers = nullptr;
} }
NS_DEFINE_NAMED_CID(NS_IOSERVICE_CID); NS_DEFINE_NAMED_CID(NS_IOSERVICE_CID);

Просмотреть файл

@ -866,10 +866,17 @@ CallTypeSniffers(void *aClosure, const uint8_t *aData, uint32_t aCount)
{ {
nsIChannel *chan = static_cast<nsIChannel*>(aClosure); nsIChannel *chan = static_cast<nsIChannel*>(aClosure);
const nsCOMArray<nsIContentSniffer>& sniffers =
gIOService->GetContentSniffers();
uint32_t length = sniffers.Count();
for (uint32_t i = 0; i < length; ++i) {
nsAutoCString newType; nsAutoCString newType;
NS_SniffContent(NS_CONTENT_SNIFFER_CATEGORY, chan, aData, aCount, newType); nsresult rv =
if (!newType.IsEmpty()) { sniffers[i]->GetMIMETypeFromContent(chan, aData, aCount, newType);
if (NS_SUCCEEDED(rv) && !newType.IsEmpty()) {
chan->SetContentType(newType); chan->SetContentType(newType);
break;
}
} }
} }
@ -879,7 +886,8 @@ nsHttpChannel::CallOnStartRequest()
mTracingEnabled = false; mTracingEnabled = false;
// Allow consumers to override our content type // 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 // 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, // 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 // because that's the one that has the initial contents. If that fails

Просмотреть файл

@ -17,6 +17,7 @@
#include "nsIPrefBranch.h" #include "nsIPrefBranch.h"
#include "nsICategoryManager.h" #include "nsICategoryManager.h"
#include "nsISupportsPrimitives.h" #include "nsISupportsPrimitives.h"
#include "nsIContentSniffer.h"
#include "nsCRT.h" #include "nsCRT.h"
@ -25,7 +26,6 @@
#include "nsIViewSourceChannel.h" #include "nsIViewSourceChannel.h"
#include "nsIHttpChannel.h" #include "nsIHttpChannel.h"
#include "nsNetCID.h" #include "nsNetCID.h"
#include "nsNetUtil.h"
#define MAX_BUFFER_SIZE 512 #define MAX_BUFFER_SIZE 512
@ -334,9 +334,9 @@ void nsUnknownDecoder::DetermineContentType(nsIRequest* aRequest)
} }
} }
NS_SniffContent(NS_DATA_SNIFFER_CATEGORY, aRequest, if (TryContentSniffers(aRequest)) {
(const uint8_t*)mBuffer, mBufferLen, mContentType); NS_ASSERTION(!mContentType.IsEmpty(),
if (!mContentType.IsEmpty()) { "Content type should be known by now.");
return; return;
} }
@ -359,6 +359,49 @@ void nsUnknownDecoder::DetermineContentType(nsIRequest* aRequest)
"Content type should be known by now."); "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) bool nsUnknownDecoder::SniffForHTML(nsIRequest* aRequest)
{ {
/* /*

Просмотреть файл

@ -60,6 +60,7 @@ protected:
// Various sniffer functions. Returning true means that a type // Various sniffer functions. Returning true means that a type
// was determined; false means no luck. // was determined; false means no luck.
bool TryContentSniffers(nsIRequest* aRequest);
bool SniffForHTML(nsIRequest* aRequest); bool SniffForHTML(nsIRequest* aRequest);
bool SniffForXML(nsIRequest* aRequest); bool SniffForXML(nsIRequest* aRequest);

Просмотреть файл

@ -6,6 +6,7 @@
#include "AsyncFaviconHelpers.h" #include "AsyncFaviconHelpers.h"
#include "nsIContentSniffer.h"
#include "nsICacheService.h" #include "nsICacheService.h"
#include "nsICacheVisitor.h" #include "nsICacheVisitor.h"
#include "nsICachingChannel.h" #include "nsICachingChannel.h"
@ -22,6 +23,8 @@
#include "nsIPrivateBrowsingService.h" #include "nsIPrivateBrowsingService.h"
#endif #endif
#define CONTENT_SNIFFING_SERVICES "content-sniffing-services"
using namespace mozilla::places; using namespace mozilla::places;
using namespace mozilla::storage; using namespace mozilla::storage;
@ -285,6 +288,55 @@ FetchIconURL(nsRefPtr<Database>& aDB,
return NS_OK; 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. * Tries to compute the expiration time for a icon from the channel.
* *
@ -644,21 +696,18 @@ AsyncFetchAndSetIconFromNetwork::OnStopRequest(nsIRequest* aRequest,
nsFaviconService* favicons = nsFaviconService::GetFaviconService(); nsFaviconService* favicons = nsFaviconService::GetFaviconService();
NS_ENSURE_STATE(favicons); NS_ENSURE_STATE(favicons);
nsresult rv;
// If fetching the icon failed, add it to the failed cache. // If fetching the icon failed, add it to the failed cache.
if (NS_FAILED(aStatusCode) || mIcon.data.Length() == 0) { if (NS_FAILED(aStatusCode) || mIcon.data.Length() == 0) {
nsCOMPtr<nsIURI> iconURI; 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); NS_ENSURE_SUCCESS(rv, rv);
rv = favicons->AddFailedFavicon(iconURI); rv = favicons->AddFailedFavicon(iconURI);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
return NS_OK; return NS_OK;
} }
NS_SniffContent(NS_DATA_SNIFFER_CATEGORY, aRequest, nsresult rv = SniffMimeTypeForIconData(aRequest, mIcon.data, mIcon.mimeType);
TO_INTBUFFER(mIcon.data), mIcon.data.Length(), NS_ENSURE_SUCCESS(rv, rv);
mIcon.mimeType);
// If the icon does not have a valid MIME type, add it to the failed cache. // If the icon does not have a valid MIME type, add it to the failed cache.
if (mIcon.mimeType.IsEmpty()) { if (mIcon.mimeType.IsEmpty()) {

Просмотреть файл

@ -59,7 +59,7 @@ class NS_COM_GLUE nsCategoryObserver MOZ_FINAL : public nsIObserver {
* then get the name of the category. * then get the name of the category.
*/ */
template<class T> template<class T>
class nsCategoryCache MOZ_FINAL : protected nsCategoryListener { class nsCategoryCache : protected nsCategoryListener {
public: public:
explicit nsCategoryCache(const char* aCategory); explicit nsCategoryCache(const char* aCategory);
~nsCategoryCache() { if (mObserver) mObserver->ListenerDied(); } ~nsCategoryCache() { if (mObserver) mObserver->ListenerDied(); }