diff --git a/modules/libpr0n/build/nsImageModule.cpp b/modules/libpr0n/build/nsImageModule.cpp index 0bfebb625ad7..9874843dac51 100644 --- a/modules/libpr0n/build/nsImageModule.cpp +++ b/modules/libpr0n/build/nsImageModule.cpp @@ -151,11 +151,15 @@ static NS_METHOD ImageRegisterProc(nsIComponentManager *aCompMgr, nsCOMPtr catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv)); if (NS_FAILED(rv)) return rv; - for (int i = 0; i < sizeof(gImageMimeTypes)/sizeof(*gImageMimeTypes); i++) { + for (unsigned i = 0; i < sizeof(gImageMimeTypes)/sizeof(*gImageMimeTypes); i++) { catMan->AddCategoryEntry("Gecko-Content-Viewers", gImageMimeTypes[i], "@mozilla.org/content/document-loader-factory;1", PR_TRUE, PR_TRUE, nsnull); } + + catMan->AddCategoryEntry("content-sniffing-services", "@mozilla.org/image/loader;1", + "@mozilla.org/image/loader;1", PR_TRUE, PR_TRUE, + nsnull); return NS_OK; } @@ -167,7 +171,7 @@ static NS_METHOD ImageUnregisterProc(nsIComponentManager *aCompMgr, nsCOMPtr catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv)); if (NS_FAILED(rv)) return rv; - for (int i = 0; i < sizeof(gImageMimeTypes)/sizeof(*gImageMimeTypes); i++) + for (unsigned i = 0; i < sizeof(gImageMimeTypes)/sizeof(*gImageMimeTypes); i++) catMan->DeleteCategoryEntry("Gecko-Content-Viewers", gImageMimeTypes[i], PR_TRUE); return NS_OK; diff --git a/modules/libpr0n/public/imgILoader.idl b/modules/libpr0n/public/imgILoader.idl index 2fcb1b09dee5..8fb423cfc9e3 100644 --- a/modules/libpr0n/public/imgILoader.idl +++ b/modules/libpr0n/public/imgILoader.idl @@ -58,7 +58,7 @@ interface nsISimpleEnumerator; * @version 0.3 * @see imagelib2 */ -[scriptable, uuid(4c8cf1e0-1dd2-11b2-aff9-c51cdbfcb6da)] +[scriptable, uuid(a32826ff-9e56-4425-a811-97a8dba64ff5)] interface imgILoader : nsISupports { /** @@ -109,12 +109,4 @@ interface imgILoader : nsISupports * @return true if a decoder is available, false otherwise */ boolean supportImageWithMimeType(in string mimeType); - - /** - * Checks if a decoder for the given contents is available. - * @param contents The first few bytes of the image - * @param length The length of contents - * @return The Content Type of the Image or null if no decoder was found. - */ - string supportImageWithContents(in string contents, in unsigned long length); }; diff --git a/modules/libpr0n/src/imgLoader.cpp b/modules/libpr0n/src/imgLoader.cpp index bb990c27b39b..054c1e0e6544 100644 --- a/modules/libpr0n/src/imgLoader.cpp +++ b/modules/libpr0n/src/imgLoader.cpp @@ -102,7 +102,7 @@ static void PrintImageDecoders() } #endif -NS_IMPL_ISUPPORTS1(imgLoader, imgILoader) +NS_IMPL_ISUPPORTS2(imgLoader, imgILoader, nsIContentSniffer) imgLoader::imgLoader() { @@ -727,18 +727,17 @@ NS_IMETHODIMP imgLoader::SupportImageWithMimeType(const char* aMimeType, PRBool return reg->IsContractIDRegistered(decoderId.get(), _retval); } -NS_IMETHODIMP imgLoader::SupportImageWithContents(const char* aContents, PRUint32 aLength, char** aContentType) +NS_IMETHODIMP imgLoader::GetMIMETypeFromContent(const PRUint8* aContents, PRUint32 aLength, nsACString& aContentType) { - return GetMimeTypeFromContent(aContents, aLength, aContentType); + return GetMimeTypeFromContent((const char*)aContents, aLength, aContentType); } /* static */ -nsresult imgLoader::GetMimeTypeFromContent(const char* aContents, PRUint32 aLength, char** aContentType) +nsresult imgLoader::GetMimeTypeFromContent(const char* aContents, PRUint32 aLength, nsACString& aContentType) { - *aContentType = nsnull; /* Is it a GIF? */ if (aLength >= 4 && !nsCRT::strncmp(aContents, "GIF8", 4)) { - *aContentType = nsCRT::strndup("image/gif", 9); + aContentType.AssignLiteral("image/gif"); } /* or a PNG? */ @@ -747,7 +746,7 @@ nsresult imgLoader::GetMimeTypeFromContent(const char* aContents, PRUint32 aLeng (unsigned char)aContents[2]==0x4E && (unsigned char)aContents[3]==0x47)) { - *aContentType = nsCRT::strndup("image/png", 9); + aContentType.AssignLiteral("image/png"); } /* maybe a JPEG (JFIF)? */ @@ -762,7 +761,7 @@ nsresult imgLoader::GetMimeTypeFromContent(const char* aContents, PRUint32 aLeng ((unsigned char)aContents[1])==0xD8 && ((unsigned char)aContents[2])==0xFF) { - *aContentType = nsCRT::strndup("image/jpeg", 10); + aContentType.AssignLiteral("image/jpeg"); } /* or how about ART? */ @@ -774,31 +773,27 @@ nsresult imgLoader::GetMimeTypeFromContent(const char* aContents, PRUint32 aLeng ((unsigned char) aContents[1])==0x47 && ((unsigned char) aContents[4])==0x00 ) { - *aContentType = nsCRT::strndup("image/x-jg", 10); + aContentType.AssignLiteral("image/x-jg"); } else if (aLength >= 2 && !nsCRT::strncmp(aContents, "BM", 2)) { - *aContentType = nsCRT::strndup("image/bmp", 9); + aContentType.AssignLiteral("image/bmp"); } // ICOs always begin with a 2-byte 0 followed by a 2-byte 1. else if (aLength >= 4 && !memcmp(aContents, "\000\000\001\000", 4)) { - *aContentType = nsCRT::strndup("image/x-icon", 12); + aContentType.AssignLiteral("image/x-icon"); } else if (aLength >= 8 && !nsCRT::strncmp(aContents, "#define ", 8)) { - *aContentType = nsCRT::strndup("image/x-xbitmap", 15); + aContentType.AssignLiteral("image/x-xbitmap"); } else { /* none of the above? I give up */ - /* don't raise an exception, simply return null */ - return NS_OK; + return NS_ERROR_NOT_AVAILABLE; } - if (*aContentType) - return NS_OK; - - return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; } /** diff --git a/modules/libpr0n/src/imgLoader.h b/modules/libpr0n/src/imgLoader.h index 049d160b0bd1..318d5baee584 100644 --- a/modules/libpr0n/src/imgLoader.h +++ b/modules/libpr0n/src/imgLoader.h @@ -38,6 +38,7 @@ * ***** END LICENSE BLOCK ***** */ #include "imgILoader.h" +#include "nsIContentSniffer.h" #ifdef LOADER_THREADSAFE #include "prlock.h" @@ -57,16 +58,17 @@ class nsILoadGroup; {0xa5, 0xb8, 0x95, 0x1f, 0x13, 0xc8, 0x46, 0xf7} \ } -class imgLoader : public imgILoader +class imgLoader : public imgILoader, public nsIContentSniffer { public: NS_DECL_ISUPPORTS NS_DECL_IMGILOADER + NS_DECL_NSICONTENTSNIFFER imgLoader(); virtual ~imgLoader(); - static nsresult GetMimeTypeFromContent(const char* aContents, PRUint32 aLength, char** aContentType); + static nsresult GetMimeTypeFromContent(const char* aContents, PRUint32 aLength, nsACString& aContentType); private: nsresult CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup *aLoadGroup, diff --git a/modules/libpr0n/src/imgRequest.cpp b/modules/libpr0n/src/imgRequest.cpp index f9104074c15b..1fb2e6123c93 100644 --- a/modules/libpr0n/src/imgRequest.cpp +++ b/modules/libpr0n/src/imgRequest.cpp @@ -844,5 +844,5 @@ static NS_METHOD sniff_mimetype_callback(nsIInputStream* in, void imgRequest::SniffMimeType(const char *buf, PRUint32 len) { - imgLoader::GetMimeTypeFromContent(buf, len, getter_Copies(mContentType)); + imgLoader::GetMimeTypeFromContent(buf, len, mContentType); } diff --git a/modules/libpr0n/src/imgRequest.h b/modules/libpr0n/src/imgRequest.h index 28556fb8edef..5459d8526c41 100644 --- a/modules/libpr0n/src/imgRequest.h +++ b/modules/libpr0n/src/imgRequest.h @@ -134,7 +134,7 @@ private: PRUint32 mImageStatus; PRUint32 mState; - nsXPIDLCString mContentType; + nsCString mContentType; nsCOMPtr mCacheEntry; /* we hold on to this to this so long as we have observers */ diff --git a/netwerk/base/public/Makefile.in b/netwerk/base/public/Makefile.in index 2fa4bd1456be..2589dc269360 100644 --- a/netwerk/base/public/Makefile.in +++ b/netwerk/base/public/Makefile.in @@ -104,6 +104,7 @@ XPIDLSRCS = \ nsIMultiPartChannel.idl \ nsIExternalProtocolHandler.idl \ nsIAuthModule.idl \ + nsIContentSniffer.idl \ $(NULL) EXPORTS = \ diff --git a/netwerk/base/public/nsIContentSniffer.idl b/netwerk/base/public/nsIContentSniffer.idl new file mode 100644 index 000000000000..f550d9812d25 --- /dev/null +++ b/netwerk/base/public/nsIContentSniffer.idl @@ -0,0 +1,56 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is necko content sniffer interface. + * + * The Initial Developer of the Original Code is + * Christian Biesinger . + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +/** + * Content sniffer interface. Components implementing this interface can + * determine a MIME type from a chunk of bytes. + */ +[scriptable, uuid(a5710331-74ec-45fb-aa85-ed3bc7c36924)] +interface nsIContentSniffer : nsISupports +{ + /** + * Given a chunk of data, determines a MIME type. + * + * @param aData Data to check + * @param aLength Length of the data + * + * @throw NS_ERROR_NOT_AVAILABLE if no MIME type could be determinted. + */ + ACString getMIMETypeFromContent([const,array,size_is(aLength)] in octet aData, + in unsigned long aLength); +}; diff --git a/netwerk/streamconv/converters/Makefile.in b/netwerk/streamconv/converters/Makefile.in index f26e3e24450c..5cfd62751438 100644 --- a/netwerk/streamconv/converters/Makefile.in +++ b/netwerk/streamconv/converters/Makefile.in @@ -53,7 +53,6 @@ REQUIRES = xpcom \ util \ pref \ uconv \ - imglib2 \ necko2 \ $(ZLIB_REQUIRES) \ $(NULL) diff --git a/netwerk/streamconv/converters/nsUnknownDecoder.cpp b/netwerk/streamconv/converters/nsUnknownDecoder.cpp index 6e1f5340eb6c..1df9090784dd 100644 --- a/netwerk/streamconv/converters/nsUnknownDecoder.cpp +++ b/netwerk/streamconv/converters/nsUnknownDecoder.cpp @@ -47,7 +47,9 @@ #include "nsXPIDLString.h" #include "nsIPrefService.h" #include "nsIPrefBranch.h" -#include "imgILoader.h" +#include "nsICategoryManager.h" +#include "nsISupportsPrimitives.h" +#include "nsIContentSniffer.h" #include "nsCRT.h" @@ -346,7 +348,7 @@ void nsUnknownDecoder::DetermineContentType(nsIRequest* aRequest) } } - if (SniffForImageMimeType(aRequest)) { + if (TryContentSniffers(aRequest)) { return; } @@ -363,18 +365,46 @@ void nsUnknownDecoder::DetermineContentType(nsIRequest* aRequest) LastDitchSniff(aRequest); } -PRBool nsUnknownDecoder::SniffForImageMimeType(nsIRequest* aRequest) +PRBool nsUnknownDecoder::TryContentSniffers(nsIRequest* aRequest) { - // Just ask libpr0n - nsCOMPtr loader(do_GetService("@mozilla.org/image/loader;1")); - if (!loader) return PR_FALSE; + // Enumerate content sniffers + nsCOMPtr catMan(do_GetService("@mozilla.org/categorymanager;1")); + if (!catMan) { + return PR_FALSE; + } - char* temp; - nsresult rv = loader->SupportImageWithContents(mBuffer, mBufferLen, &temp); - if (NS_FAILED(rv) || !temp) return PR_FALSE; + nsCOMPtr sniffers; + catMan->EnumerateCategory("content-sniffing-services", getter_AddRefs(sniffers)); + if (!sniffers) { + return PR_FALSE; + } - mContentType.Adopt(temp); - return PR_TRUE; + PRBool hasMore; + while (NS_SUCCEEDED(sniffers->HasMoreElements(&hasMore)) && hasMore) { + nsCOMPtr elem; + sniffers->GetNext(getter_AddRefs(elem)); + NS_ASSERTION(elem, "No element even though hasMore returned true!?"); + + nsCOMPtr sniffer_id(do_QueryInterface(elem)); + NS_ASSERTION(sniffer_id, "element is no nsISupportsCString!?"); + nsCAutoString contractid; + nsresult rv = sniffer_id->GetData(contractid); + if (NS_FAILED(rv)) { + continue; + } + + nsCOMPtr sniffer(do_GetService(contractid.get())); + if (!sniffer) { + continue; + } + + rv = sniffer->GetMIMETypeFromContent((const PRUint8*)mBuffer, mBufferLen, mContentType); + if (NS_SUCCEEDED(rv)) { + return PR_TRUE; + } + } + + return PR_FALSE; } PRBool nsUnknownDecoder::SniffForHTML(nsIRequest* aRequest) diff --git a/netwerk/streamconv/converters/nsUnknownDecoder.h b/netwerk/streamconv/converters/nsUnknownDecoder.h index 1787ab545d5d..78461f511d78 100644 --- a/netwerk/streamconv/converters/nsUnknownDecoder.h +++ b/netwerk/streamconv/converters/nsUnknownDecoder.h @@ -88,7 +88,7 @@ protected: // Various sniffer functions. Returning PR_TRUE means that a type // was determined; PR_FALSE means no luck. - PRBool SniffForImageMimeType(nsIRequest* aRequest); + PRBool TryContentSniffers(nsIRequest* aRequest); PRBool SniffForHTML(nsIRequest* aRequest); PRBool SniffForXML(nsIRequest* aRequest);