diff --git a/mozilla/camino/src/download/SaveHeaderSniffer.mm b/mozilla/camino/src/download/SaveHeaderSniffer.mm index a601352b71a..0a702a7e748 100644 --- a/mozilla/camino/src/download/SaveHeaderSniffer.mm +++ b/mozilla/camino/src/download/SaveHeaderSniffer.mm @@ -272,7 +272,7 @@ nsresult nsHeaderSniffer::PerformSave(nsIURI* inOriginalURI) if (!mimeService) return rv; nsCOMPtr mimeInfo; - rv = mimeService->GetFromMIMEType(mContentType.get(), getter_AddRefs(mimeInfo)); + rv = mimeService->GetFromTypeAndExtension(mContentType.get(), nsnull, getter_AddRefs(mimeInfo)); if (!mimeInfo) return rv; diff --git a/mozilla/dom/src/base/nsMimeTypeArray.cpp b/mozilla/dom/src/base/nsMimeTypeArray.cpp index 0bd5f3216d5..786081048b8 100644 --- a/mozilla/dom/src/base/nsMimeTypeArray.cpp +++ b/mozilla/dom/src/base/nsMimeTypeArray.cpp @@ -135,8 +135,8 @@ MimeTypeArrayImpl::NamedItem(const nsAString& aName, nsCOMPtr mimeSrv = do_GetService("@mozilla.org/mime;1"); if (mimeSrv) { nsCOMPtr mimeInfo; - mimeSrv->GetFromMIMEType(NS_ConvertUCS2toUTF8(aName).get(), - getter_AddRefs(mimeInfo)); + mimeSrv->GetFromTypeAndExtension(NS_ConvertUCS2toUTF8(aName).get(), nsnull, + getter_AddRefs(mimeInfo)); if (mimeInfo) { // Now we check whether we can really claim to support this type nsMIMEInfoHandleAction action = nsIMIMEInfo::saveToDisk; diff --git a/mozilla/editor/ui/composer/content/ComposerCommands.js b/mozilla/editor/ui/composer/content/ComposerCommands.js index 8ce82228bb7..c825f27a221 100644 --- a/mozilla/editor/ui/composer/content/ComposerCommands.js +++ b/mozilla/editor/ui/composer/content/ComposerCommands.js @@ -766,7 +766,7 @@ function GetExtensionBasedOnMimeType(aMIMEType) mimeService = Components.classes["@mozilla.org/mime;1"].getService(); mimeService = mimeService.QueryInterface(Components.interfaces.nsIMIMEService); - var mimeInfo = mimeService.GetFromMIMEType(aMIMEType); + var mimeInfo = mimeService.GetFromTypeAndExtension(aMIMEType, null); if (!mimeInfo) return ""; var fileExtension = mimeInfo.primaryExtension; diff --git a/mozilla/embedding/browser/activex/src/control/PropertyDlg.cpp b/mozilla/embedding/browser/activex/src/control/PropertyDlg.cpp index e8f98f25788..1ff93595c73 100644 --- a/mozilla/embedding/browser/activex/src/control/PropertyDlg.cpp +++ b/mozilla/embedding/browser/activex/src/control/PropertyDlg.cpp @@ -110,7 +110,7 @@ LRESULT CPPageDlg::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& nsCOMPtr mimeInfo; nsCAutoString contentType; contentType.AssignWithConversion(mType); - mimeService->GetFromMIMEType(contentType.get(), getter_AddRefs(mimeInfo)); + mimeService->GetFromTypeAndExtension(contentType.get(), nsnull, getter_AddRefs(mimeInfo)); if (mimeInfo) { nsXPIDLString description; diff --git a/mozilla/embedding/browser/cocoa/src/SaveHeaderSniffer.mm b/mozilla/embedding/browser/cocoa/src/SaveHeaderSniffer.mm index 4d56c707410..c096ece9285 100644 --- a/mozilla/embedding/browser/cocoa/src/SaveHeaderSniffer.mm +++ b/mozilla/embedding/browser/cocoa/src/SaveHeaderSniffer.mm @@ -253,7 +253,7 @@ nsresult nsHeaderSniffer::PerformSave(nsIURI* inOriginalURI) if (!mimeService) return rv; nsCOMPtr mimeInfo; - rv = mimeService->GetFromMIMEType(mContentType.get(), getter_AddRefs(mimeInfo)); + rv = mimeService->GetFromTypeAndExtension(mContentType.get(), nsnull, getter_AddRefs(mimeInfo)); if (!mimeInfo) return rv; diff --git a/mozilla/embedding/browser/powerplant/source/CHeaderSniffer.cpp b/mozilla/embedding/browser/powerplant/source/CHeaderSniffer.cpp index 8047c248dd9..2c3be96fe20 100644 --- a/mozilla/embedding/browser/powerplant/source/CHeaderSniffer.cpp +++ b/mozilla/embedding/browser/powerplant/source/CHeaderSniffer.cpp @@ -281,7 +281,7 @@ nsresult CHeaderSniffer::PerformSave(nsIURI* inOriginalURI, const ESaveFormat in if (!mimeService) return rv; nsCOMPtr mimeInfo; - rv = mimeService->GetFromMIMEType(mContentType.get(), getter_AddRefs(mimeInfo)); + rv = mimeService->GetFromTypeAndExtension(mContentType.get(), nsnull, getter_AddRefs(mimeInfo)); if (!mimeInfo) return rv; diff --git a/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp b/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp index fcd10e97af4..cc458346e63 100644 --- a/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp +++ b/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp @@ -1285,7 +1285,7 @@ nsWebBrowserPersist::GetExtensionForContentType(const PRUnichar *aContentType, P nsCOMPtr mimeInfo; nsCAutoString contentType; contentType.AssignWithConversion(aContentType); - mMIMEService->GetFromMIMEType(contentType.get(), getter_AddRefs(mimeInfo)); + mMIMEService->GetFromTypeAndExtension(contentType.get(), nsnull, getter_AddRefs(mimeInfo)); if (mimeInfo) { nsXPIDLCString ext; @@ -2058,8 +2058,8 @@ nsWebBrowserPersist::CalculateAndAppendFileExt(nsIURI *aURI, nsIChannel *aChanne if (!contentType.IsEmpty()) { nsCOMPtr mimeInfo; - mMIMEService->GetFromMIMEType( - contentType.get(), getter_AddRefs(mimeInfo)); + mMIMEService->GetFromTypeAndExtension( + contentType.get(), nsnull, getter_AddRefs(mimeInfo)); nsCOMPtr localFile; GetLocalFileFromURI(aURI, getter_AddRefs(localFile)); diff --git a/mozilla/mailnews/base/src/nsMessenger.cpp b/mozilla/mailnews/base/src/nsMessenger.cpp index 0cf5c05d10f..4462ea6eeb2 100644 --- a/mozilla/mailnews/base/src/nsMessenger.cpp +++ b/mozilla/mailnews/base/src/nsMessenger.cpp @@ -1807,7 +1807,7 @@ nsSaveMsgListener::OnStartRequest(nsIRequest* request, nsISupports* aSupport) if (mimeService) { nsCOMPtr mimeinfo; - if (NS_SUCCEEDED(mimeService->GetFromMIMEType(m_contentType.get(), getter_AddRefs(mimeinfo)))) + if (NS_SUCCEEDED(mimeService->GetFromTypeAndExtension(m_contentType.get(), nsnull, getter_AddRefs(mimeinfo)))) { PRUint32 aMacType; PRUint32 aMacCreator; diff --git a/mozilla/mailnews/mime/src/mimedrft.cpp b/mozilla/mailnews/mime/src/mimedrft.cpp index 9dd0786bcf7..dc2c6ace749 100644 --- a/mozilla/mailnews/mime/src/mimedrft.cpp +++ b/mozilla/mailnews/mime/src/mimedrft.cpp @@ -1893,7 +1893,7 @@ mime_decompose_file_init_fn ( void *stream_closure, MimeHeaders *headers ) if (NS_SUCCEEDED(rv) && mimeFinder) { nsCOMPtr mimeInfo = nsnull; - rv = mimeFinder->GetFromMIMEType(contentType.get(), getter_AddRefs(mimeInfo)); + rv = mimeFinder->GetFromTypeAndExtension(contentType.get(), nsnull, getter_AddRefs(mimeInfo)); if (NS_SUCCEEDED(rv) && mimeInfo) { nsXPIDLCString fileExtension; diff --git a/mozilla/mailnews/mime/src/mimemoz2.cpp b/mozilla/mailnews/mime/src/mimemoz2.cpp index 964b0b972be..3b7d321cdda 100644 --- a/mozilla/mailnews/mime/src/mimemoz2.cpp +++ b/mozilla/mailnews/mime/src/mimemoz2.cpp @@ -282,7 +282,7 @@ ValidateRealName(nsMsgAttachmentData *aAttach, MimeHeaders *aHdrs) if (NS_SUCCEEDED(rv) && mimeFinder) { nsIMIMEInfo *mimeInfo = nsnull; - rv = mimeFinder->GetFromMIMEType(contentType.get(), &mimeInfo); + rv = mimeFinder->GetFromTypeAndExtension(contentType.get(), nsnull, &mimeInfo); if (NS_SUCCEEDED(rv) && mimeInfo) { char *aFileExtension = nsnull; diff --git a/mozilla/modules/libpr0n/decoders/icon/mac/nsIconChannel.cpp b/mozilla/modules/libpr0n/decoders/icon/mac/nsIconChannel.cpp index e871f9ac9cc..f117affbd9b 100644 --- a/mozilla/modules/libpr0n/decoders/icon/mac/nsIconChannel.cpp +++ b/mozilla/modules/libpr0n/decoders/icon/mac/nsIconChannel.cpp @@ -330,16 +330,11 @@ NS_IMETHODIMP nsIconChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports // if we were given an explicit content type, use it.... nsCOMPtr mimeInfo; - if (mimeService) + if (mimeService && (!contentType.IsEmpty() || !fileExtension.IsEmpty())) { - if (!contentType.IsEmpty()) - { - mimeService->GetFromMIMEType(contentType.get(), getter_AddRefs(mimeInfo)); - } - if (!mimeInfo) // try to grab an extension for the dummy file in the url. - { - mimeService->GetFromExtension(fileExtension.get(), getter_AddRefs(mimeInfo)); - } + mimeService->GetFromTypeAndExtension(contentType.get(), + fileExtension.get(), + getter_AddRefs(mimeInfo)); } // if we don't have enough info to fetch an application icon, bail diff --git a/mozilla/modules/libpr0n/decoders/icon/os2/nsIconChannel.cpp b/mozilla/modules/libpr0n/decoders/icon/os2/nsIconChannel.cpp index ba502b1cdd9..7cf89c8fafc 100644 --- a/mozilla/modules/libpr0n/decoders/icon/os2/nsIconChannel.cpp +++ b/mozilla/modules/libpr0n/decoders/icon/os2/nsIconChannel.cpp @@ -409,7 +409,7 @@ NS_IMETHODIMP nsIconChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports nsCOMPtr mimeObject; NS_ENSURE_SUCCESS(rv, rv); - mimeService->GetFromMIMEType(contentType.get(), getter_AddRefs(mimeObject)); + mimeService->GetFromTypeAndExtension(contentType.get(), nsnull, getter_AddRefs(mimeObject)); if (mimeObject) { nsXPIDLCString fileExt; diff --git a/mozilla/modules/libpr0n/decoders/icon/win/nsIconChannel.cpp b/mozilla/modules/libpr0n/decoders/icon/win/nsIconChannel.cpp index 8028d7066f0..20035d8913f 100644 --- a/mozilla/modules/libpr0n/decoders/icon/win/nsIconChannel.cpp +++ b/mozilla/modules/libpr0n/decoders/icon/win/nsIconChannel.cpp @@ -331,7 +331,7 @@ NS_IMETHODIMP nsIconChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports nsCOMPtr mimeObject; NS_ENSURE_SUCCESS(rv, rv); - mimeService->GetFromMIMEType(contentType.get(), getter_AddRefs(mimeObject)); + mimeService->GetFromTypeAndExtension(contentType.get(), nsnull, getter_AddRefs(mimeObject)); if (mimeObject) { nsXPIDLCString fileExt; diff --git a/mozilla/netwerk/mime/public/nsIMIMEService.idl b/mozilla/netwerk/mime/public/nsIMIMEService.idl index 624d55acaf5..ae940d452ad 100644 --- a/mozilla/netwerk/mime/public/nsIMIMEService.idl +++ b/mozilla/netwerk/mime/public/nsIMIMEService.idl @@ -63,21 +63,13 @@ [scriptable, uuid(6C424C90-2FE7-11d3-A164-0050041CAF44)] interface nsIMIMEService : nsISupports { - /* Retrieves a registered nsIMIMEInfo interface associated - * with the given file extension. - * - * @param A file extension (excluding the dot ('.')). - * @return A nsIMIMEInfo interface. + /* Retrieves an nsIMIMEInfo using both the extension + * and the type of a file. The type is given preference + * during the lookup. One of aMIMEType and aFileExt + * can be null. At least one of aMIMEType and aFileExt + * must be non-null and nonempty. */ - nsIMIMEInfo GetFromExtension(in string aFileExt); - - /* Retrieves a registered nsIMIMEInfo interface associated - * with the given MIME type. - * - * @param A MIME type. - * @return A nsIMIMEInfo interface. - */ - nsIMIMEInfo GetFromMIMEType(in string aMIMEType); + nsIMIMEInfo GetFromTypeAndExtension(in string aMIMEType, in string aFileExt); /* Retrieves a string representation of the MIME type * associated with this file extension. diff --git a/mozilla/uriloader/exthandler/beos/nsOSHelperAppService.cpp b/mozilla/uriloader/exthandler/beos/nsOSHelperAppService.cpp index 20f66d48086..001ad691e9a 100644 --- a/mozilla/uriloader/exthandler/beos/nsOSHelperAppService.cpp +++ b/mozilla/uriloader/exthandler/beos/nsOSHelperAppService.cpp @@ -51,17 +51,8 @@ #include #include -#ifdef MOZ_LOGGING -#define FORCE_PR_LOG /* Allow logging in the release build */ -#endif /* MOZ_LOGGING */ -#include "prlog.h" - -#ifdef PR_LOGGING -static PRLogModuleInfo *gOSHelperLog = PR_NewLogModule("nsOSHelperAppService"); -#endif /* PR_LOGGING */ - -#define LOG(args) PR_LOG(gOSHelperLog, PR_LOG_DEBUG, args) -#define LOG_ENABLED() PR_LOG_TEST(gOSHelperLog, PR_LOG_DEBUG) +#define LOG(args) PR_LOG(mLog, PR_LOG_DEBUG, args) +#define LOG_ENABLED() PR_LOG_TEST(mLog, PR_LOG_DEBUG) nsOSHelperAppService::nsOSHelperAppService() : nsExternalHelperAppService() { @@ -220,9 +211,9 @@ nsresult nsOSHelperAppService::SetMIMEInfoForType(const char *aMIMEType, nsIMIME rv = GetFileTokenForPath(NS_ConvertUTF8toUCS2(path.Path()).get(), getter_AddRefs(handlerFile)); if (NS_SUCCEEDED(rv)) { - mimeInfo->SetPreferredApplicationHandler(handlerFile); - mimeInfo->SetPreferredAction(nsIMIMEInfo::useHelperApp); - mimeInfo->SetApplicationDescription(NS_ConvertUTF8toUCS2(path.Leaf()).get()); + mimeInfo->SetDefaultApplicationHandler(handlerFile); + mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault); + mimeInfo->SetDefaultDescription(NS_ConvertUTF8toUCS2(path.Leaf()).get()); LOG((" Preferred App: %s\n",path.Leaf())); doSave = false; } @@ -243,16 +234,12 @@ nsresult nsOSHelperAppService::SetMIMEInfoForType(const char *aMIMEType, nsIMIME return rv; } -NS_IMETHODIMP nsOSHelperAppService::GetFromExtension(const char *aFileExt, +nsresult nsOSHelperAppService::GetMimeInfoFromExtension(const char *aFileExt, nsIMIMEInfo ** _retval) { // if the extension is null, return immediately if (!aFileExt || !*aFileExt) return NS_ERROR_INVALID_ARG; - // first, see if the base class already has an entry.... - nsresult rv = nsExternalHelperAppService::GetFromExtension(aFileExt, _retval); - if (NS_SUCCEEDED(rv) && *_retval) return NS_OK; // okay we got an entry so we are done. - LOG(("Here we do an extension lookup for '%s'\n", aFileExt)); BString fileExtToUse(aFileExt); @@ -294,16 +281,12 @@ NS_IMETHODIMP nsOSHelperAppService::GetFromExtension(const char *aFileExt, return rv; } -NS_IMETHODIMP nsOSHelperAppService::GetFromMIMEType(const char *aMIMEType, +nsresult nsOSHelperAppService::GetMimeInfoFromMIMEType(const char *aMIMEType, nsIMIMEInfo ** _retval) { // if the mime type is null, return immediately - if (!aMIMEType) + if (!aMIMEType || !*aMIMEType) return NS_ERROR_INVALID_ARG; - // first, see if the base class already has an entry.... - nsresult rv = nsExternalHelperAppService::GetFromMIMEType(aMIMEType, _retval); - if (NS_SUCCEEDED(rv) && *_retval) return NS_OK; // okay we got an entry so we are done. - LOG(("Here we do a mimetype lookup for '%s'\n", aMIMEType)); BMessage data; @@ -327,6 +310,20 @@ NS_IMETHODIMP nsOSHelperAppService::GetFromMIMEType(const char *aMIMEType, return rv; } +already_AddRefed +nsOSHelperAppService::GetMIMEInfoFromOS(const char *aMIMEType, const char *aFileExt) +{ + nsIMIMEInfo* mi = nsnull; + GetMimeInfoFromMIMEType(aMIMEType, &mi); + if (mi) + return mi; + + GetMimeInfoFromExtension(aFileExt, &mi); + if (mi && aMIMEType && *aMIMEType) + mi->SetMIMEType(aMIMEType); + return mi; +} + nsresult nsOSHelperAppService::GetFileTokenForPath(const PRUnichar* platformAppPath, nsIFile ** aFile) { LOG(("-- nsOSHelperAppService::GetFileTokenForPath: '%s'\n", NS_ConvertUCS2toUTF8(platformAppPath).get())); diff --git a/mozilla/uriloader/exthandler/beos/nsOSHelperAppService.h b/mozilla/uriloader/exthandler/beos/nsOSHelperAppService.h index edc1c573c99..d3f6d65e655 100644 --- a/mozilla/uriloader/exthandler/beos/nsOSHelperAppService.h +++ b/mozilla/uriloader/exthandler/beos/nsOSHelperAppService.h @@ -54,9 +54,7 @@ public: // override nsIExternalHelperAppService methods.... NS_IMETHOD LaunchAppWithTempFile(nsIMIMEInfo *aMIMEInfo, nsIFile * aTempFile); - // method overrides for mime.types and mime.info look up steps - NS_IMETHODIMP GetFromExtension(const char *aFileExt, nsIMIMEInfo **_retval); - NS_IMETHODIMP GetFromMIMEType(const char *aMIMEType, nsIMIMEInfo **_retval); + already_AddRefed GetMIMEInfoFromOS(const char *aMIMEType, const char * aFileExt); // override nsIExternalProtocolService methods NS_IMETHOD ExternalProtocolHandlerExists(const char * aProtocolScheme, PRBool * aHandlerExists); @@ -70,6 +68,8 @@ public: protected: nsresult SetMIMEInfoForType(const char *aMIMEType, nsIMIMEInfo **_retval); + nsresult GetMimeInfoFromExtension(const char *aFileExt, nsIMIMEInfo **_retval); + nsresult GetMimeInfoFromMIMEType(const char *aMIMEType, nsIMIMEInfo **_retval); }; #endif // nsOSHelperAppService_h__ diff --git a/mozilla/uriloader/exthandler/mac/nsOSHelperAppService.cpp b/mozilla/uriloader/exthandler/mac/nsOSHelperAppService.cpp index 0a8531c369b..a6aa484cada 100644 --- a/mozilla/uriloader/exthandler/mac/nsOSHelperAppService.cpp +++ b/mozilla/uriloader/exthandler/mac/nsOSHelperAppService.cpp @@ -186,66 +186,62 @@ nsresult nsOSHelperAppService::GetFileTokenForPath(const PRUnichar * platformApp // method overrides --> use internet config information for mime type lookup. /////////////////////////// -NS_IMETHODIMP nsOSHelperAppService::GetFromExtension(const char * aFileExt, nsIMIMEInfo ** aMIMEInfo) +NS_IMETHODIMP nsOSHelperAppService::GetFromTypeAndExtension(const char * aType, const char * aFileExt, nsIMIMEInfo ** aMIMEInfo) { // first, ask our base class.... - nsresult rv = nsExternalHelperAppService::GetFromExtension(aFileExt, aMIMEInfo); + nsresult rv = nsExternalHelperAppService::GetFromTypeAndExtension(aType, aFileExt, aMIMEInfo); if (NS_SUCCEEDED(rv) && *aMIMEInfo) { UpdateCreatorInfo(*aMIMEInfo); } return rv; } - -nsresult nsOSHelperAppService::GetMIMEInfoForExtensionFromOS(const char * aFileExt, nsIMIMEInfo ** aMIMEInfo) -{ - nsresult rv; - - // ask the internet config service to look it up for us... - nsCOMPtr icService (do_GetService(NS_INTERNETCONFIGSERVICE_CONTRACTID)); - if (icService) - { - rv = icService->GetMIMEInfoFromExtension(aFileExt, aMIMEInfo); - // if we got an entry, don't waste time hitting IC for this information next time, store it in our - // hash table.... - // XXX Once cache can be invalidated, add the mime info to it. See bug 121644 - // if (NS_SUCCEEDED(rv) && *aMIMEInfo) - // AddMimeInfoToCache(*aMIMEInfo); - } - - if (!*aMIMEInfo) rv = NS_ERROR_FAILURE; - return rv; -} -NS_IMETHODIMP nsOSHelperAppService::GetFromMIMEType(const char * aMIMEType, nsIMIMEInfo ** aMIMEInfo) +already_AddRefed +nsOSHelperAppService::GetMIMEInfoFromOS(const char * aMIMEType, + const char * aFileExt) { - // first, ask our base class.... - nsresult rv = nsExternalHelperAppService::GetFromMIMEType(aMIMEType, aMIMEInfo); - if (NS_SUCCEEDED(rv) && *aMIMEInfo) - { - UpdateCreatorInfo(*aMIMEInfo); - } - return rv; -} - -nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char * aMIMEType, nsIMIMEInfo ** aMIMEInfo) -{ - nsresult rv; + nsIMIMEInfo* mimeInfo = nsnull; // ask the internet config service to look it up for us... nsCOMPtr icService (do_GetService(NS_INTERNETCONFIGSERVICE_CONTRACTID)); + PR_LOG(mLog, PR_LOG_DEBUG, ("Mac: HelperAppService lookup for type '%s' ext '%s' (IC: 0x%p)\n", + aMIMEType, aFileExt, icService.get())); if (icService) { - rv = icService->FillInMIMEInfo(aMIMEType, nsnull, aMIMEInfo); - // if we got an entry, don't waste time hitting IC for this information next time, store it in our - // hash table.... - // XXX Once cache can be invalidated, add the mime info to it. See bug 121644 - // if (NS_SUCCEEDED(rv) && *aMIMEInfo) - // AddMimeInfoToCache(*aMIMEInfo); + nsCOMPtr miByType, miByExt; + if (aMIMEType && *aMIMEType) + icService->FillInMIMEInfo(aMIMEType, aFileExt, getter_AddRefs(miByType)); + + PRBool hasDefault = PR_FALSE; + if (miByType) + miByType->GetHasDefaultHandler(&hasDefault); + + if (aFileExt && *aFileExt && (!hasDefault || !miByType)) { + icService->GetMIMEInfoFromExtension(aFileExt, getter_AddRefs(miByExt)); + if (miByExt && aMIMEType) + miByExt->SetMIMEType(aMIMEType); + } + PR_LOG(mLog, PR_LOG_DEBUG, ("OS gave us: By Type: 0x%p By Ext: 0x%p type has default: %s\n", + miByType.get(), miByExt.get(), hasDefault ? "true" : "false")); + + // If we got two matches, and the type has no default app, copy default app + if (!hasDefault && miByType && miByExt) { + nsCOMPtr defaultApp; + nsXPIDLString desc; + miByExt->GetDefaultDescription(getter_Copies(desc)); + miByExt->GetDefaultApplicationHandler(getter_AddRefs(defaultApp)); + + miByType->SetDefaultDescription(desc.get()); + miByType->SetDefaultApplicationHandler(defaultApp); + } + if (miByType) + miByType.swap(mimeInfo); + else if (miByExt) + miByExt.swap(mimeInfo); } - if (!*aMIMEInfo) rv = NS_ERROR_FAILURE; - return rv; + return mimeInfo; } // we never want to use a hard coded value for the creator and file type for the mac. always look these values up diff --git a/mozilla/uriloader/exthandler/mac/nsOSHelperAppService.h b/mozilla/uriloader/exthandler/mac/nsOSHelperAppService.h index 2dbd8ea173f..6134b6760b0 100644 --- a/mozilla/uriloader/exthandler/mac/nsOSHelperAppService.h +++ b/mozilla/uriloader/exthandler/mac/nsOSHelperAppService.h @@ -45,10 +45,8 @@ public: NS_IMETHOD LoadUrl(nsIURI * aURL); // method overrides --> used to hook the mime service into internet config.... - NS_IMETHOD GetFromExtension(const char * aFileExt, nsIMIMEInfo ** aMIMEInfo); - NS_IMETHOD GetFromMIMEType(const char * aMIMEType, nsIMIMEInfo ** aMIMEInfo); - nsresult GetMIMEInfoForExtensionFromOS(const char * aFileExt, nsIMIMEInfo ** aMIMEInfo); - nsresult GetMIMEInfoForMimeTypeFromOS(const char * aMIMEType, nsIMIMEInfo ** aMIMEInfo); + NS_IMETHOD GetFromTypeAndExtension(const char * aType, const char * aFileExt, nsIMIMEInfo ** aMIMEInfo); + already_AddRefed GetMIMEInfoFromOS(const char * aMIMEType, const char * aFileExt); // GetFileTokenForPath must be implemented by each platform. // platformAppPath --> a platform specific path to an application that we got out of the diff --git a/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp b/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp index 6206e1bd0f1..4a80e8048f5 100644 --- a/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -91,6 +91,15 @@ #include "nsCRT.h" #include "plstr.h" +#ifdef PR_LOGGING +PRLogModuleInfo* nsExternalHelperAppService::mLog = nsnull; +#endif + +// Using level 3 here because the OSHelperAppServices use a log level +// of PR_LOG_DEBUG (4), and we want less detailed output here +// Using 3 instead of PR_LOG_WARN because we don't output warnings +#define LOG(args) PR_LOG(mLog, 3, args) + static const char NEVER_ASK_PREF_BRANCH[] = "browser.helperApps.neverAsk."; static const char NEVER_ASK_FOR_SAVE_TO_DISK_PREF[] = "saveToDisk"; static const char NEVER_ASK_FOR_OPEN_FILE_PREF[] = "openFile"; @@ -203,6 +212,14 @@ nsresult nsExternalHelperAppService::Init() nsCOMPtr obs = do_GetService("@mozilla.org/observer-service;1", &rv); NS_ENSURE_SUCCESS(rv, rv); +#ifdef PR_LOGGING + if (!mLog) { + mLog = PR_NewLogModule("HelperAppService"); + if (!mLog) + return NS_ERROR_OUT_OF_MEMORY; + } +#endif + return obs->AddObserver(this, "profile-before-change", PR_TRUE); } @@ -279,80 +296,46 @@ NS_IMETHODIMP nsExternalHelperAppService::DoContent(const char *aMimeContentType nsIStreamListener ** aStreamListener) { nsCOMPtr mimeInfo; - nsCAutoString fileExtension, query; + nsCAutoString fileExtension; - // (1) Try to find a mime object by looking the mime type - GetFromMIMEType(aMimeContentType, getter_AddRefs(mimeInfo)); - // Get some stuff we will need later nsCOMPtr channel = do_QueryInterface(aRequest); nsCOMPtr url; PRBool methodIsPost = PR_FALSE; if (channel) { - nsCOMPtr uri; - channel->GetURI(getter_AddRefs(uri)); - url = do_QueryInterface(uri); - nsCOMPtr httpChan = do_QueryInterface(channel); if (httpChan) { nsCAutoString requestMethod; httpChan->GetRequestMethod(requestMethod); methodIsPost = requestMethod.Equals("POST"); } + + nsCOMPtr uri; + channel->GetURI(getter_AddRefs(uri)); + + // If the method is post, don't bother getting the file extension; + // it will belong to a CGI script anyway + if (uri && !methodIsPost) { + url = do_QueryInterface(uri); + + if (url) { + nsCAutoString query; + url->GetQuery(query); + // Only get the extension if the query is empty; if it isn't, then the + // extension likely belongs to a cgi script and isn't helpful + if (query.IsEmpty()) + url->GetFileExtension(fileExtension); + } + } } - if (url) - { - if (!mimeInfo) - { - // if we couldn't find one, don't give up yet! Try and see if there is an extension in the - // url itself... - // See if this URL specifies the output from a cgi script. - // If so, then the extension in the URL doesn't tell us - // anything about the content of the data, so don't try - // to find a handler based on that. - // Same if it's the result of POSTed data - url->GetQuery(query); - if (query.IsEmpty() && !methodIsPost) { - url->GetFileExtension(fileExtension); - GetFromExtension(fileExtension.get(), getter_AddRefs(mimeInfo)); - // only over write mimeInfo if we got a non-null mime info object. - if (mimeInfo) - { - // The OS might have thought this extension was a different mime type. - // We must reset this to match the actual mime type. Otherwise, we - // won't use this MIMEInfo when we see the real mime type next time. - mimeInfo->SetMIMEType(aMimeContentType); - } - } - } - else - { - // Get default app/description. - PRBool hasDefaultApp = PR_FALSE; - nsXPIDLString defaultDescription; - mimeInfo->GetHasDefaultHandler(&hasDefaultApp); - mimeInfo->GetDefaultDescription(getter_Copies(defaultDescription)); - // If neither description nor app are specified, then we try to get - // these from the per-platform OS settings based on the file extension. - if (defaultDescription.IsEmpty() && !hasDefaultApp) - { - nsCOMPtr osInfo; - url->GetFileExtension(fileExtension); - if (NS_SUCCEEDED(GetMIMEInfoForExtensionFromOS(fileExtension.get(), getter_AddRefs(osInfo)))) - { - // Extract default application and default description. - nsCOMPtr defaultApp; - osInfo->GetDefaultApplicationHandler(getter_AddRefs(defaultApp)); - osInfo->GetDefaultDescription(getter_Copies(defaultDescription)); - // Copy to result mime info object. - mimeInfo->SetDefaultApplicationHandler(defaultApp); - mimeInfo->SetDefaultDescription(defaultDescription.get()); - } - } - } - } + LOG(("HelperAppService::DoContent: mime '%s', extension '%s'\n", + aMimeContentType, fileExtension.get())); + + // (1) Try to find a mime object by looking at the mime type/extension + GetFromTypeAndExtension(aMimeContentType, fileExtension.get(), getter_AddRefs(mimeInfo)); + LOG(("Type/Ext lookup found 0x%p\n", mimeInfo.get())); // (2) if we don't have a match yet, see if this type is in our list of extras. if (!mimeInfo) @@ -365,12 +348,10 @@ NS_IMETHODIMP nsExternalHelperAppService::DoContent(const char *aMimeContentType * right; any info we get from extras on this type is pretty much * useless.... */ - if (PL_strcasecmp(aMimeContentType, APPLICATION_OCTET_STREAM) != 0) { + if (PL_strcasecmp(aMimeContentType, APPLICATION_OCTET_STREAM) != 0) #endif GetMIMEInfoForMimeTypeFromExtras(aMimeContentType, getter_AddRefs(mimeInfo)); -#ifdef XP_WIN - } -#endif + LOG(("Searched extras, found 0x%p\n", mimeInfo.get())); } // (3) if we STILL don't have a mime object for this content type then give up @@ -387,6 +368,7 @@ NS_IMETHODIMP nsExternalHelperAppService::DoContent(const char *aMimeContentType mimeInfo->SetFileExtensions(fileExtension.get()); mimeInfo->SetMIMEType(aMimeContentType); // we may need to add a new method to nsIMIMEService so we can add this mime info object to our mime service. + LOG(("Gave up, created new mimeinfo 0x%p\n", mimeInfo.get())); } *aStreamListener = nsnull; @@ -395,17 +377,11 @@ NS_IMETHODIMP nsExternalHelperAppService::DoContent(const char *aMimeContentType // set it as the primary extension. In either case, fileExtension // should be the primary extension once we are doen. // Ignore URL extension if data is output from a cgi script. - if (!methodIsPost && fileExtension.IsEmpty() && url) { - url->GetQuery(query); - if (query.IsEmpty()) { - url->GetFileExtension(fileExtension); - } - } - PRBool matches = PR_FALSE; if (!fileExtension.IsEmpty()) { mimeInfo->ExtensionExists(fileExtension.get(), &matches); } + LOG(("Extension '%s' matches mime info: '%s'\n", fileExtension.get(), matches? "yes" : "no")); if (matches) { mimeInfo->SetPrimaryExtension(fileExtension.get()); } else { @@ -413,7 +389,7 @@ NS_IMETHODIMP nsExternalHelperAppService::DoContent(const char *aMimeContentType mimeInfo->GetPrimaryExtension(getter_Copies(buf)); fileExtension = buf; } - + // this code is incomplete and just here to get things started.. nsExternalAppHandler * handler = CreateNewExternalHandler(mimeInfo, fileExtension.get(), aWindowContext); if (!handler) @@ -758,20 +734,10 @@ nsresult nsExternalHelperAppService::GetMIMEInfoForExtensionFromDS(const char * return rv; } -nsresult nsExternalHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char * aContentType, nsIMIMEInfo ** aMIMEInfo) +already_AddRefed nsExternalHelperAppService::GetMIMEInfoFromOS(const char * aContentType, const char * aFileExt) { - NS_PRECONDITION(aMIMEInfo, "Null out param"); - *aMIMEInfo = nsnull; - // Should be implemented by per-platform derived classes. - return NS_ERROR_NOT_IMPLEMENTED; -} - -nsresult nsExternalHelperAppService::GetMIMEInfoForExtensionFromOS(const char * aFileExtension, nsIMIMEInfo ** aMIMEInfo) -{ - NS_PRECONDITION(aMIMEInfo, "Null out param"); - *aMIMEInfo = nsnull; - // Should be implemented by per-platform derived classes. - return NS_ERROR_NOT_IMPLEMENTED; + NS_NOTREACHED("Should be implemented by per-platform derived classes"); + return nsnull; } ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -2107,89 +2073,101 @@ nsExternalAppHandler::SetLoadCookie(nsISupports * aLoadCookie) // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// nsIMIMEService methods -NS_IMETHODIMP nsExternalHelperAppService::GetFromExtension(const char *aFileExt, nsIMIMEInfo **_retval) +// Copies the user settings from one mime info to another +// Note: the mime types are assumed to be already equal, as are the mac type & creator codes! +static void CopyUserSettings(nsIMIMEInfo* aSource, nsIMIMEInfo* aDest) { - nsresult rv = NS_OK; - nsCAutoString fileExt(aFileExt); - if (fileExt.IsEmpty()) return NS_ERROR_FAILURE; + // First, copy the extension list + // let's not clear the extension list. - ToLowerCase(fileExt); - // if the file extension contains a '.', our hash key doesn't include the '.' - // so skip over it... - if (fileExt.First() == '.') - fileExt.Cut(0, 1); // cut the '.' - - // Query the user provided data source - rv = GetMIMEInfoForExtensionFromDS(aFileExt, _retval); - - // if we don't have a match in mimeTypes.rdf, then try the per-platform OS settings - if (!*_retval) - { - rv = GetMIMEInfoForExtensionFromOS(aFileExt, _retval); - } - else - { - // Get OS settings so we can fill the "default" fields in the MIMEInfo we got - // from mimeTypes.rdf. - nsCOMPtr osInfo; - if (NS_SUCCEEDED(GetMIMEInfoForExtensionFromOS(aFileExt, getter_AddRefs(osInfo)))) - { - // Extract default application and default description. - nsCOMPtr defaultApp; - nsXPIDLString defaultDescription; - osInfo->GetDefaultApplicationHandler(getter_AddRefs(defaultApp)); - osInfo->GetDefaultDescription(getter_Copies(defaultDescription)); - // Copy to result mime info object. - (*_retval)->SetDefaultApplicationHandler(defaultApp); - (*_retval)->SetDefaultDescription(defaultDescription.get()); + nsCOMPtr enumer; + aSource->GetFileExtensions(getter_AddRefs(enumer)); + if (enumer) { + nsCAutoString ext; + PRBool hasMore; + while (NS_SUCCEEDED(enumer->HasMore(&hasMore)) && hasMore) { + enumer->GetNext(ext); + aDest->AppendExtension(ext.get()); } } - // if we still don't have a match, then we give up, we don't know - // anything about it... return an error. + nsXPIDLCString primaryExt; + aSource->GetPrimaryExtension(getter_Copies(primaryExt)); + if (!primaryExt.IsEmpty()) + aDest->SetPrimaryExtension(primaryExt); - if (!*_retval) rv = NS_ERROR_FAILURE; - return rv; + // description + nsXPIDLString desc; + aSource->GetDescription(getter_Copies(desc)); + aDest->SetDescription(desc.get()); + + // Preferred application handler & desc + nsCOMPtr prefer; + aSource->GetPreferredApplicationHandler(getter_AddRefs(prefer)); + aDest->SetPreferredApplicationHandler(prefer); + + aSource->GetApplicationDescription(getter_Copies(desc)); + aDest->SetApplicationDescription(desc.get()); + + // Preferred action & always ask + nsMIMEInfoHandleAction action; + aSource->GetPreferredAction(&action); + aDest->SetPreferredAction(action); + + PRBool alwaysAsk = PR_TRUE; + aSource->GetAlwaysAskBeforeHandling(&alwaysAsk); + aDest->SetAlwaysAskBeforeHandling(alwaysAsk); } -NS_IMETHODIMP nsExternalHelperAppService::GetFromMIMEType(const char *aMIMEType, nsIMIMEInfo **_retval) +// nsIMIMEService methods +NS_IMETHODIMP nsExternalHelperAppService::GetFromTypeAndExtension(const char *aMIMEType, const char *aFileExt, nsIMIMEInfo **_retval) { - nsresult rv = NS_OK; - nsCAutoString MIMEType(aMIMEType); - ToLowerCase(MIMEType); + NS_PRECONDITION((aMIMEType && *aMIMEType) || + (aFileExt && *aFileExt), + "Give me something to work with"); + LOG(("Getting mimeinfo from type '%s' ext '%s'\n", aMIMEType, aFileExt)); - // Query the user provided data source - rv = GetMIMEInfoForMimeTypeFromDS(aMIMEType, _retval); + *_retval = nsnull; + // Ask the OS for a mime info + *_retval = GetMIMEInfoFromOS(aMIMEType, aFileExt).get(); + LOG(("OS gave back 0x%p\n", *_retval)); - // if we don't have a match in mimeTypes.rdf, then try the per-platform OS settings - if (!*_retval) - { - rv = GetMIMEInfoForMimeTypeFromOS(aMIMEType, _retval); + // Now, let's see if we can find something in our datasource + nsCOMPtr dsInfoType; + if (aMIMEType && *aMIMEType) + GetMIMEInfoForMimeTypeFromDS(aMIMEType, getter_AddRefs(dsInfoType)); + + LOG(("Data source: Via type 0x%p\n", dsInfoType.get())); + + // Copy user settings over to our retval if we found a type, + // otherwise just give back what we found in the DS + if (dsInfoType) { + if (!*_retval) + dsInfoType.swap(*_retval); + else + CopyUserSettings(dsInfoType, *_retval); } - else - { - // Get OS settings so we can fill the "default" fields in the MIMEInfo we got - // from mimeTypes.rdf. - nsCOMPtr osInfo; - if (NS_SUCCEEDED(GetMIMEInfoForMimeTypeFromOS(aMIMEType, getter_AddRefs(osInfo)))) - { - // Extract default application and default description. - nsCOMPtr defaultApp; - nsXPIDLString defaultDescription; - osInfo->GetDefaultApplicationHandler(getter_AddRefs(defaultApp)); - osInfo->GetDefaultDescription(getter_Copies(defaultDescription)); - // Copy to result mime info object. - (*_retval)->SetDefaultApplicationHandler(defaultApp); - (*_retval)->SetDefaultDescription(defaultDescription.get()); + else { + // No type match, try extension match + nsCOMPtr dsInfoExt; + if (aFileExt && *aFileExt) { + GetMIMEInfoForExtensionFromDS(aFileExt, getter_AddRefs(dsInfoExt)); + LOG(("Data source: Via ext 0x%p\n", dsInfoExt.get())); + } + if (dsInfoExt) { + if (!*_retval) + dsInfoExt.swap(*_retval); + else + CopyUserSettings(dsInfoExt, *_retval); } } - // if we still don't have a match, then we give up, we don't know anything about it... - // return an error. + // if we don't have a match, then we give up, we don't know + // anything about it... return an error. + + if (!*_retval) return NS_ERROR_FAILURE; + return NS_OK; - if (!*_retval) rv = NS_ERROR_FAILURE; - return rv; } NS_IMETHODIMP nsExternalHelperAppService::GetTypeFromExtension(const char *aFileExt, char **aContentType) @@ -2205,7 +2183,7 @@ NS_IMETHODIMP nsExternalHelperAppService::GetTypeFromExtension(const char *aFile nsresult rv = NS_OK; nsCOMPtr info; - rv = GetFromExtension(aFileExt, getter_AddRefs(info)); + rv = GetFromTypeAndExtension(nsnull, aFileExt, getter_AddRefs(info)); if (NS_FAILED(rv)) { // Try the plugins const char* mimeType; diff --git a/mozilla/uriloader/exthandler/nsExternalHelperAppService.h b/mozilla/uriloader/exthandler/nsExternalHelperAppService.h index 1b7863c5442..2d938575716 100644 --- a/mozilla/uriloader/exthandler/nsExternalHelperAppService.h +++ b/mozilla/uriloader/exthandler/nsExternalHelperAppService.h @@ -23,6 +23,11 @@ #ifndef nsExternalHelperAppService_h__ #define nsExternalHelperAppService_h__ +#ifdef MOZ_LOGGING +#define FORCE_PR_LOG +#endif +#include "prlog.h" + #include "nsIExternalHelperAppService.h" #include "nsIExternalProtocolService.h" #include "nsIURIContentListener.h" @@ -75,34 +80,42 @@ public: nsresult Init(); // CreateNewExternalHandler is implemented only by the base class... - // create an external app handler and binds it with a mime info object which represents - // how we want to dispose of this content - // aFileExtension --> the extension we need to append to our temp file INCLUDING the ".". i.e. .mp3 - nsExternalAppHandler * CreateNewExternalHandler(nsIMIMEInfo * aMIMEInfo, const char * aFileExtension, nsISupports * aWindowContext); + // create an external app handler and binds it with a mime info object which + // represents how we want to dispose of this content + // aFileExtension --> the extension we need to append to our temp file + // INCLUDING the ".". i.e. .mp3 + nsExternalAppHandler * CreateNewExternalHandler(nsIMIMEInfo * aMIMEInfo, + const char * aFileExtension, + nsISupports * aWindowContext); - // GetMIMEInfoForMimeTypeFromDS --> Given a content type, look up the user override information to - // see if we have a mime info object representing this content type. The user over ride information is contained + // GetMIMEInfoForMimeTypeFromDS --> Given a content type, look up the user + // override information to see if we have a mime info object representing + // this content type. The user over ride information is contained // in a in memory data source.... - nsresult GetMIMEInfoForMimeTypeFromDS(const char * aContentType, nsIMIMEInfo ** aMIMEInfo); + nsresult GetMIMEInfoForMimeTypeFromDS(const char * aContentType, + nsIMIMEInfo ** aMIMEInfo); - // GetMIMEInfoForExtensionFromDS --> Given an extension, look up the user override information to - // see if we have a mime info object representing this extension. The user over ride information is contained + // GetMIMEInfoForExtensionFromDS --> Given an extension, look up the user + // override information to see if we have a mime info object representing + // this extension. The user over ride information is contained // in a in memory data source.... - nsresult GetMIMEInfoForExtensionFromDS(const char * aFileExtension, nsIMIMEInfo ** aMIMEInfo); + nsresult GetMIMEInfoForExtensionFromDS(const char * aFileExtension, + nsIMIMEInfo ** aMIMEInfo); - // GetMIMEInfoForMimeTypeFromOS --> Given a content type, look up the system default information to - // see if we can create a mime info object for this content type. - virtual nsresult GetMIMEInfoForMimeTypeFromOS(const char * aContentType, nsIMIMEInfo ** aMIMEInfo); - - // GetMIMEInfoForExtensionFromOS --> Given an extension, look up the system default information to - // see if we can create a mime info object for this extension. - virtual nsresult GetMIMEInfoForExtensionFromOS(const char * aFileExtension, nsIMIMEInfo ** aMIMEInfo); + // Given a mimetype and an extension, looks up a mime info from the os. + // The mime type is given preference. This function follows the same rules + // as nsIMIMEService::GetFromTypeAndExtension + virtual already_AddRefed GetMIMEInfoFromOS(const char * aMIMEType, + const char * aFileExt); // GetFileTokenForPath must be implemented by each platform. - // platformAppPath --> a platform specific path to an application that we got out of the - // rdf data source. This can be a mac file spec, a unix path or a windows path depending on the platform + // platformAppPath --> a platform specific path to an application that we + // got out of the rdf data source. This can be a mac + // file spec, a unix path or a windows path depending + // on the platform // aFile --> an nsIFile representation of that platform application path. - virtual nsresult GetFileTokenForPath(const PRUnichar * platformAppPath, nsIFile ** aFile) = 0; + virtual nsresult GetFileTokenForPath(const PRUnichar * platformAppPath, + nsIFile ** aFile) = 0; // helper routine used to test whether a given mime type is in our // mimeTypes.rdf data source @@ -123,38 +136,57 @@ protected: PRBool mDataSourceInitialized; - // helper routines for digesting the data source and filling in a mime info object for a given - // content type inside that data source. - nsresult FillTopLevelProperties(const char * aContentType, nsIRDFResource * aContentTypeNodeResource, - nsIRDFService * aRDFService, nsIMIMEInfo * aMIMEInfo); - nsresult FillContentHandlerProperties(const char * aContentType, nsIRDFResource * aContentTypeNodeResource, - nsIRDFService * aRDFService, nsIMIMEInfo * aMIMEInfo); + // helper routines for digesting the data source and filling in a mime info + // object for a given content type inside that data source. + nsresult FillTopLevelProperties(const char * aContentType, + nsIRDFResource * aContentTypeNodeResource, + nsIRDFService * aRDFService, + nsIMIMEInfo * aMIMEInfo); + nsresult FillContentHandlerProperties(const char * aContentType, + nsIRDFResource * aContentTypeNodeResource, + nsIRDFService * aRDFService, + nsIMIMEInfo * aMIMEInfo); - // a small helper function which gets the target for a given source and property...QIs to a literal - // and returns a CONST ptr to the string value of that target - nsresult FillLiteralValueFromTarget(nsIRDFResource * aSource, nsIRDFResource * aProperty, const PRUnichar ** aLiteralValue); + // a small helper function which gets the target for a given source and + // property... QIs to a literal and returns a CONST ptr to the string value + // of that target + nsresult FillLiteralValueFromTarget(nsIRDFResource * aSource, + nsIRDFResource * aProperty, + const PRUnichar ** aLiteralValue); - virtual nsresult GetMIMEInfoForMimeTypeFromExtras(const char * aContentType, nsIMIMEInfo ** aMIMEInfo ); - virtual nsresult GetMIMEInfoForExtensionFromExtras(const char * aContentType, nsIMIMEInfo ** aMIMEInfo ); + virtual nsresult GetMIMEInfoForMimeTypeFromExtras(const char * aContentType, + nsIMIMEInfo ** aMIMEInfo); + virtual nsresult GetMIMEInfoForExtensionFromExtras(const char * aContentType, + nsIMIMEInfo ** aMIMEInfo); protected: - // functions related to the tempory file cleanup service provided by nsExternalHelperAppService +#ifdef PR_LOGGING + // NSPR Logging + static PRLogModuleInfo* mLog; +#endif + // functions related to the tempory file cleanup service provided by + // nsExternalHelperAppService nsresult ExpungeTemporaryFiles(); nsCOMArray mTemporaryFilesList; }; // An external app handler is just a small little class that presents itself as // a nsIStreamListener. It saves the incoming data into a temp file. The handler -// is bound to an application when it is created. When it receives an OnStopRequest -// it launches the application using the temp file it has stored the data into. -// we create a handler every time we have to process data using a helper app. +// is bound to an application when it is created. When it receives an +// OnStopRequest it launches the application using the temp file it has +// stored the data into. We create a handler every time we have to process +// data using a helper app. -// we need to read the data out of the incoming stream into a buffer which we can then use -// to write the data into the output stream representing the temp file... +// we need to read the data out of the incoming stream into a buffer which we +// can then use to write the data into the output stream representing the +// temp file... #define DATA_BUFFER_SIZE (4096*2) -class nsExternalAppHandler : public nsIStreamListener, public nsIHelperAppLauncher, public nsIURIContentListener, - public nsIInterfaceRequestor, public nsIObserver +class nsExternalAppHandler : public nsIStreamListener, + public nsIHelperAppLauncher, + public nsIURIContentListener, + public nsIInterfaceRequestor, + public nsIObserver { public: NS_DECL_ISUPPORTS @@ -168,7 +200,9 @@ public: nsExternalAppHandler(); virtual ~nsExternalAppHandler(); - virtual nsresult Init(nsIMIMEInfo * aMIMEInfo, const char * aFileExtension, nsISupports * aWindowContext, nsExternalHelperAppService *aHelperAppService); + virtual nsresult Init(nsIMIMEInfo * aMIMEInfo, const char * aFileExtension, + nsISupports * aWindowContext, + nsExternalHelperAppService *aHelperAppService); protected: nsCOMPtr mTempFile; @@ -177,15 +211,17 @@ protected: nsCOMPtr mMimeInfo; nsCOMPtr mOutStream; // output stream to the temp file... nsCOMPtr mWindowContext; - // the following field is set if we were processing an http channel that had a content disposition header - // which specified the SUGGESTED file name we should present to the user in the save to disk dialog. + // the following field is set if we were processing an http channel that had + // a content disposition header which specified the SUGGESTED file name we + // should present to the user in the save to disk dialog. nsString mSuggestedFileName; - // the canceled flag is set if the user canceled the launching of this application before we finished - // saving the data to a temp file... + // the canceled flag is set if the user canceled the launching of this + // application before we finished saving the data to a temp file... PRPackedBool mCanceled; - // have we received information from the user about how they want to dispose of this content... + // have we received information from the user about how they want to + // dispose of this content... PRPackedBool mReceivedDispositionInfo; PRPackedBool mStopRequestIssued; PRPackedBool mProgressListenerInitialized; @@ -195,35 +231,39 @@ protected: PRInt32 mContentLength; PRInt32 mProgress; // Number of bytes received (for sending progress notifications). - // when we are told to save the temp file to disk (in a more permament location) before we are done - // writing the content to a temp file, then we need to remember the final destination until we are ready to - // use it. + // when we are told to save the temp file to disk (in a more permament + // location) before we are done writing the content to a temp file, then + // we need to remember the final destination until we are ready to use it. nsCOMPtr mFinalFileDestination; char * mDataBuffer; nsresult SetUpTempFile(nsIChannel * aChannel); - // when we download a helper app, we are going to retarget all load notifications into our own docloader - // and load group instead of using the window which initiated the load....RetargetLoadNotifications contains - // that information... + // when we download a helper app, we are going to retarget all load + // notifications into our own docloader and load group instead of + // using the window which initiated the load....RetargetLoadNotifications + // contains that information... nsresult RetargetLoadNotifications(nsIRequest *request); // if the user tells us how they want to dispose of the content and // we still haven't finished downloading while they were deciding, // then create a progress listener of some kind so they know // what's going on... nsresult CreateProgressListener(); - nsresult PromptForSaveToFile(nsILocalFile ** aNewFile, const nsAFlatString &aDefaultFile, const nsAFlatString &aDefaultFileExt); - // if the passed in channel is an nsIHTTPChannel, we'll attempt to extract a suggested file name - // from the content disposition header... + nsresult PromptForSaveToFile(nsILocalFile ** aNewFile, + const nsAFlatString &aDefaultFile, + const nsAFlatString &aDefaultFileExt); + // if the passed in channel is an nsIHTTPChannel, we'll attempt to extract + // a suggested file name from the content disposition header... void ExtractSuggestedFileNameFromChannel(nsIChannel * aChannel); - // after we're done prompting the user for any information, if the original channel had a refresh url associated - // with it (which might point to a "thank you for downloading" kind of page, then process that....It is safe - // to invoke this method multiple times. We'll clear mOriginalChannel after it's called and this ensures we won't - // call it again.... + // after we're done prompting the user for any information, if the original + // channel had a refresh url associated with it (which might point to a + // "thank you for downloading" kind of page, then process that....It is safe + // to invoke this method multiple times. We'll clear mOriginalChannel after + // it's called and this ensures we won't call it again.... void ProcessAnyRefreshTags(); - // an internal method used to actually move the temp file to the final destination - // once we done receiving data AND have showed the progress dialog. + // an internal method used to actually move the temp file to the final + // destination once we done receiving data AND have showed the progress dialog nsresult MoveFile(nsIFile * aNewFileLocation); // an internal method used to actually launch a helper app given the temp file // once we are done receiving data AND have showed the progress dialog. diff --git a/mozilla/uriloader/exthandler/os2/nsOSHelperAppService.cpp b/mozilla/uriloader/exthandler/os2/nsOSHelperAppService.cpp index 771b0f80f76..e5612a12065 100644 --- a/mozilla/uriloader/exthandler/os2/nsOSHelperAppService.cpp +++ b/mozilla/uriloader/exthandler/os2/nsOSHelperAppService.cpp @@ -49,23 +49,9 @@ static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID); // XXX need to conver #define INCL_DOS #include -#ifdef MOZ_LOGGING -#define FORCE_PR_LOG /* Allow logging in the release build */ -#endif /* MOZ_LOGGING */ -#include "prlog.h" +#define LOG(args) PR_LOG(mLog, PR_LOG_DEBUG, args) +#define LOG_ENABLED() PR_LOG_TEST(mLog, PR_LOG_DEBUG) -#ifdef PR_LOGGING -static PRLogModuleInfo *gOSHelperLog = PR_NewLogModule("nsOSHelperAppService"); -#endif /* PR_LOGGING */ - -#define LOG(args) PR_LOG(gOSHelperLog, PR_LOG_DEBUG, args) -#define LOG_ENABLED() PR_LOG_TEST(gOSHelperLog, PR_LOG_DEBUG) -static nsresult -UnescapeCommand(const nsAString& aEscapedCommand, - const nsAString& aMajorType, - const nsAString& aMinorType, - nsHashtable& aTypeOptions, - nsACString& aUnEscapedCommand); static nsresult FindSemicolon(nsAString::const_iterator& aSemicolon_iter, const nsAString::const_iterator& aEnd_iter); @@ -76,83 +62,10 @@ ParseMIMEType(const nsAString::const_iterator& aStart_iter, nsAString::const_iterator& aMinorTypeStart, nsAString::const_iterator& aMinorTypeEnd, const nsAString::const_iterator& aEnd_iter); -static nsresult -GetFileLocation(const char* aPrefName, - const char* aEnvVarName, - PRUnichar** aFileLocation); -static nsresult -LookUpTypeAndDescription(const nsAString& aFileExtension, - nsAString& aMajorType, - nsAString& aMinorType, - nsAString& aDescription); inline PRBool IsNetscapeFormat(const nsAString& aBuffer); -static nsresult -CreateInputStream(const nsAString& aFilename, - nsIFileInputStream** aFileInputStream, - nsILineInputStream** aLineInputStream, - nsAString& aBuffer, - PRBool* aNetscapeFormat, - PRBool* aMore); - -static nsresult -GetTypeAndDescriptionFromMimetypesFile(const nsAString& aFilename, - const nsAString& aFileExtension, - nsAString& aMajorType, - nsAString& aMinorType, - nsAString& aDescription); - -static nsresult -LookUpExtensionsAndDescription(const nsAString& aMajorType, - const nsAString& aMinorType, - nsAString& aFileExtensions, - nsAString& aDescription); -static nsresult -GetExtensionsAndDescriptionFromMimetypesFile(const nsAString& aFilename, - const nsAString& aMajorType, - const nsAString& aMinorType, - nsAString& aFileExtensions, - nsAString& aDescription); - -static nsresult -ParseNetscapeMIMETypesEntry(const nsAString& aEntry, - nsAString::const_iterator& aMajorTypeStart, - nsAString::const_iterator& aMajorTypeEnd, - nsAString::const_iterator& aMinorTypeStart, - nsAString::const_iterator& aMinorTypeEnd, - nsAString& aExtensions, - nsAString::const_iterator& aDescriptionStart, - nsAString::const_iterator& aDescriptionEnd); - - -static nsresult -ParseNormalMIMETypesEntry(const nsAString& aEntry, - nsAString::const_iterator& aMajorTypeStart, - nsAString::const_iterator& aMajorTypeEnd, - nsAString::const_iterator& aMinorTypeStart, - nsAString::const_iterator& aMinorTypeEnd, - nsAString& aExtensions, - nsAString::const_iterator& aDescriptionStart, - nsAString::const_iterator& aDescriptionEnd); - -static nsresult -LookUpHandlerAndDescription(const nsAString& aMajorType, - const nsAString& aMinorType, - nsHashtable& aTypeOptions, - nsAString& aHandler, - nsAString& aDescription, - nsAString& aMozillaFlags); -static nsresult -GetHandlerAndDescriptionFromMailcapFile(const nsAString& aFilename, - const nsAString& aMajorType, - const nsAString& aMinorType, - nsHashtable& aTypeOptions, - nsAString& aHandler, - nsAString& aDescription, - nsAString& aMozillaFlags); - nsOSHelperAppService::nsOSHelperAppService() : nsExternalHelperAppService() { } @@ -274,12 +187,13 @@ NS_IMETHODIMP nsOSHelperAppService::LaunchAppWithTempFile(nsIMIMEInfo * aMIMEInf * Ideally this needs the mime type, mime type options, and location of the * temporary file, but this last can't be got from here */ -static nsresult -UnescapeCommand(const nsAString& aEscapedCommand, - const nsAString& aMajorType, - const nsAString& aMinorType, - nsHashtable& aTypeOptions, - nsACString& aUnEscapedCommand) { +// static +nsresult +nsOSHelperAppService::UnescapeCommand(const nsAString& aEscapedCommand, + const nsAString& aMajorType, + const nsAString& aMinorType, + nsHashtable& aTypeOptions, + nsACString& aUnEscapedCommand) { LOG(("-- UnescapeCommand")); LOG(("Command to escape: '%s'\n", NS_LossyConvertUCS2toASCII(aEscapedCommand).get())); @@ -367,10 +281,11 @@ ParseMIMEType(const nsAString::const_iterator& aStart_iter, return NS_OK; } -static nsresult -GetFileLocation(const char* aPrefName, - const char* aEnvVarName, - PRUnichar** aFileLocation) { +// static +nsresult +nsOSHelperAppService::GetFileLocation(const char* aPrefName, + const char* aEnvVarName, + PRUnichar** aFileLocation) { LOG(("-- GetFileLocation. Pref: '%s' EnvVar: '%s'\n", aPrefName, aEnvVarName)); @@ -442,8 +357,9 @@ GetFileLocation(const char* aPrefName, /* Get the mime.types file names from prefs and look up info in them based on extension */ -static nsresult -LookUpTypeAndDescription(const nsAString& aFileExtension, +// static +nsresult +nsOSHelperAppService::LookUpTypeAndDescription(const nsAString& aFileExtension, nsAString& aMajorType, nsAString& aMinorType, nsAString& aDescription) { @@ -496,13 +412,14 @@ IsNetscapeFormat(const nsAString& aBuffer) { * Leaves the first line of the file in aBuffer and sets the format to * PR_TRUE for netscape files and false for normail ones */ -static nsresult -CreateInputStream(const nsAString& aFilename, - nsIFileInputStream ** aFileInputStream, - nsILineInputStream ** aLineInputStream, - nsAString& aBuffer, - PRBool * aNetscapeFormat, - PRBool * aMore) { +// static +nsresult +nsOSHelperAppService::CreateInputStream(const nsAString& aFilename, + nsIFileInputStream ** aFileInputStream, + nsILineInputStream ** aLineInputStream, + nsAString& aBuffer, + PRBool * aNetscapeFormat, + PRBool * aMore) { LOG(("-- CreateInputStream")); nsresult rv = NS_OK; @@ -545,12 +462,13 @@ CreateInputStream(const nsAString& aFilename, /* Open the file, read the first line, decide what type of file it is, then get info based on extension */ -static nsresult -GetTypeAndDescriptionFromMimetypesFile(const nsAString& aFilename, - const nsAString& aFileExtension, - nsAString& aMajorType, - nsAString& aMinorType, - nsAString& aDescription) { +// static +nsresult +nsOSHelperAppService::GetTypeAndDescriptionFromMimetypesFile(const nsAString& aFilename, + const nsAString& aFileExtension, + nsAString& aMajorType, + nsAString& aMinorType, + nsAString& aDescription) { LOG(("-- GetTypeAndDescriptionFromMimetypesFile\n")); LOG(("Getting type and description from types file '%s'\n", NS_LossyConvertUCS2toASCII(aFilename).get())); @@ -668,11 +586,12 @@ GetTypeAndDescriptionFromMimetypesFile(const nsAString& aFilename, /* Get the mime.types file names from prefs and look up info in them based on mimetype */ -static nsresult -LookUpExtensionsAndDescription(const nsAString& aMajorType, - const nsAString& aMinorType, - nsAString& aFileExtensions, - nsAString& aDescription) { +// static +nsresult +nsOSHelperAppService::LookUpExtensionsAndDescription(const nsAString& aMajorType, + const nsAString& aMinorType, + nsAString& aFileExtensions, + nsAString& aDescription) { LOG(("-- LookUpExtensionsAndDescription for type '%s/%s'\n", NS_LossyConvertUCS2toASCII(aMajorType).get(), NS_LossyConvertUCS2toASCII(aMinorType).get())); @@ -710,12 +629,13 @@ LookUpExtensionsAndDescription(const nsAString& aMajorType, /* Open the file, read the first line, decide what type of file it is, then get info based on extension */ -static nsresult -GetExtensionsAndDescriptionFromMimetypesFile(const nsAString& aFilename, - const nsAString& aMajorType, - const nsAString& aMinorType, - nsAString& aFileExtensions, - nsAString& aDescription) { +// static +nsresult +nsOSHelperAppService::GetExtensionsAndDescriptionFromMimetypesFile(const nsAString& aFilename, + const nsAString& aMajorType, + const nsAString& aMinorType, + nsAString& aFileExtensions, + nsAString& aDescription) { LOG(("-- GetExtensionsAndDescriptionFromMimetypesFile\n")); LOG(("Getting extensions and description from types file '%s'\n", NS_LossyConvertUCS2toASCII(aFilename).get())); @@ -835,15 +755,16 @@ GetExtensionsAndDescriptionFromMimetypesFile(const nsAString& aFilename, * * type=foo/bar; options description="Some type" exts="baz" */ -static nsresult -ParseNetscapeMIMETypesEntry(const nsAString& aEntry, - nsAString::const_iterator& aMajorTypeStart, - nsAString::const_iterator& aMajorTypeEnd, - nsAString::const_iterator& aMinorTypeStart, - nsAString::const_iterator& aMinorTypeEnd, - nsAString& aExtensions, - nsAString::const_iterator& aDescriptionStart, - nsAString::const_iterator& aDescriptionEnd) { +// static +nsresult +nsOSHelperAppService::ParseNetscapeMIMETypesEntry(const nsAString& aEntry, + nsAString::const_iterator& aMajorTypeStart, + nsAString::const_iterator& aMajorTypeEnd, + nsAString::const_iterator& aMinorTypeStart, + nsAString::const_iterator& aMinorTypeEnd, + nsAString& aExtensions, + nsAString::const_iterator& aDescriptionStart, + nsAString::const_iterator& aDescriptionEnd) { LOG(("-- ParseNetscapeMIMETypesEntry\n")); NS_ASSERTION(!aEntry.IsEmpty(), "Empty Netscape MIME types entry being parsed."); @@ -984,15 +905,16 @@ ParseNetscapeMIMETypesEntry(const nsAString& aEntry, * * major/minor ext1 ext2 ext3 */ -static nsresult -ParseNormalMIMETypesEntry(const nsAString& aEntry, - nsAString::const_iterator& aMajorTypeStart, - nsAString::const_iterator& aMajorTypeEnd, - nsAString::const_iterator& aMinorTypeStart, - nsAString::const_iterator& aMinorTypeEnd, - nsAString& aExtensions, - nsAString::const_iterator& aDescriptionStart, - nsAString::const_iterator& aDescriptionEnd) { +// static +nsresult +nsOSHelperAppService::ParseNormalMIMETypesEntry(const nsAString& aEntry, + nsAString::const_iterator& aMajorTypeStart, + nsAString::const_iterator& aMajorTypeEnd, + nsAString::const_iterator& aMinorTypeStart, + nsAString::const_iterator& aMinorTypeEnd, + nsAString& aExtensions, + nsAString::const_iterator& aDescriptionStart, + nsAString::const_iterator& aDescriptionEnd) { LOG(("-- ParseNormalMIMETypesEntry\n")); NS_ASSERTION(!aEntry.IsEmpty(), "Empty Normal MIME types entry being parsed."); @@ -1063,13 +985,14 @@ ParseNormalMIMETypesEntry(const nsAString& aEntry, return NS_OK; } -static nsresult -LookUpHandlerAndDescription(const nsAString& aMajorType, - const nsAString& aMinorType, - nsHashtable& aTypeOptions, - nsAString& aHandler, - nsAString& aDescription, - nsAString& aMozillaFlags) { +// static +nsresult +nsOSHelperAppService::LookUpHandlerAndDescription(const nsAString& aMajorType, + const nsAString& aMinorType, + nsHashtable& aTypeOptions, + nsAString& aHandler, + nsAString& aDescription, + nsAString& aMozillaFlags) { LOG(("-- LookUpHandlerAndDescription for type '%s/%s'\n", NS_LossyConvertUCS2toASCII(aMajorType).get(), NS_LossyConvertUCS2toASCII(aMinorType).get())); @@ -1109,14 +1032,15 @@ LookUpHandlerAndDescription(const nsAString& aMajorType, return rv; } -static nsresult -GetHandlerAndDescriptionFromMailcapFile(const nsAString& aFilename, - const nsAString& aMajorType, - const nsAString& aMinorType, - nsHashtable& aTypeOptions, - nsAString& aHandler, - nsAString& aDescription, - nsAString& aMozillaFlags) { +// static +nsresult +nsOSHelperAppService::GetHandlerAndDescriptionFromMailcapFile(const nsAString& aFilename, + const nsAString& aMajorType, + const nsAString& aMinorType, + nsHashtable& aTypeOptions, + nsAString& aHandler, + nsAString& aDescription, + nsAString& aMozillaFlags) { LOG(("-- GetHandlerAndDescriptionFromMailcapFile\n")); LOG(("Getting handler and description from mailcap file '%s'\n", @@ -1564,11 +1488,11 @@ nsresult nsOSHelperAppService::GetFileTokenForPath(const PRUnichar * platformApp #endif } -nsresult nsOSHelperAppService::GetMIMEInfoForExtensionFromOS(const char *aFileExt, - nsIMIMEInfo ** _retval) { +already_AddRefed +nsOSHelperAppService::GetFromExtension(const char *aFileExt) { // if the extension is null, return immediately if (!aFileExt || !*aFileExt) - return NS_ERROR_INVALID_ARG; + return nsnull; LOG(("Here we do an extension lookup for '%s'\n", aFileExt)); @@ -1583,7 +1507,7 @@ nsresult nsOSHelperAppService::GetMIMEInfoForExtensionFromOS(const char *aFileEx minorType, mime_types_description); if (NS_FAILED(rv)) - return rv; + return nsnull; LOG(("Type/Description results: majorType='%s', minorType='%s', description='%s'\n", NS_LossyConvertUCS2toASCII(majorType).get(), @@ -1592,12 +1516,13 @@ nsresult nsOSHelperAppService::GetMIMEInfoForExtensionFromOS(const char *aFileEx if (majorType.IsEmpty() && minorType.IsEmpty()) { // we didn't get a type mapping, so we can't do anything useful - return NS_ERROR_FAILURE; + return nsnull; } - nsCOMPtr mimeInfo(do_CreateInstance(NS_MIMEINFO_CONTRACTID, &rv)); + nsIMIMEInfo* mimeInfo = nsnull; + rv = CallCreateInstance(NS_MIMEINFO_CONTRACTID, &mimeInfo); if (NS_FAILED(rv)) - return rv; + return nsnull; mimeType = majorType + NS_LITERAL_STRING("/") + minorType; mimeInfo->SetMIMEType(NS_ConvertUCS2toUTF8(mimeType).get()); @@ -1644,21 +1569,19 @@ nsresult nsOSHelperAppService::GetMIMEInfoForExtensionFromOS(const char *aFileEx } else { mimeInfo->SetPreferredAction(nsIMIMEInfo::saveToDisk); } - - *_retval = mimeInfo; - NS_ADDREF(*_retval); + + return mimeInfo; // XXX Once cache can be invalidated, add the mime info to it. See bug 121644 // AddMimeInfoToCache(*_retval); - - return NS_OK; + } -nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char *aMIMEType, - nsIMIMEInfo ** _retval) { +already_AddRefed +nsOSHelperAppService::GetFromType(const char *aMIMEType) { // if the extension is null, return immediately if (!aMIMEType) - return NS_ERROR_INVALID_ARG; + return nsnull; LOG(("Here we do a mimetype lookup for '%s'\n", aMIMEType)); nsresult rv; @@ -1683,7 +1606,7 @@ nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char *aMIMETyp minorTypeStart, minorTypeEnd, end_iter); if (NS_FAILED(rv)) { - return rv; + return nsnull; } nsDependentSubstring majorType(majorTypeStart, majorTypeEnd); @@ -1719,7 +1642,7 @@ nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char *aMIMETyp if (handler.IsEmpty()) { // we have no useful info.... - return NS_ERROR_FAILURE; + return nsnull; } mailcap_description.Trim(" \t\""); @@ -1728,12 +1651,12 @@ nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char *aMIMETyp minorType, extensions, mime_types_description); - - nsCOMPtr mimeInfo(do_CreateInstance(NS_MIMEINFO_CONTRACTID, &rv)); - + + nsIMIMEInfo* mimeInfo = nsnull; + rv = CallCreateInstance(NS_MIMEINFO_CONTRACTID, &mimeInfo); if (NS_FAILED(rv)) - return rv; - + return nsnull; + mimeInfo->SetFileExtensions(PromiseFlatCString(NS_ConvertUCS2toUTF8(extensions)).get()); mimeInfo->SetMIMEType(aMIMEType); if (! mime_types_description.IsEmpty()) { @@ -1741,7 +1664,7 @@ nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char *aMIMETyp } else { mimeInfo->SetDescription(mailcap_description.get()); } - + rv = NS_ERROR_FAILURE; nsCOMPtr handlerFile; rv = GetFileTokenForPath(handler.get(), getter_AddRefs(handlerFile)); @@ -1753,11 +1676,38 @@ nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char *aMIMETyp } else { mimeInfo->SetPreferredAction(nsIMIMEInfo::saveToDisk); } - - *_retval = mimeInfo; - NS_ADDREF(*_retval); - - // XXX Once cache can be invalidated, add the mime info to it. See bug 121644 - // AddMimeInfoToCache(*_retval); - return NS_OK; + + return mimeInfo; } + + +already_AddRefed +nsOSHelperAppService::GetMIMEInfoFromOS(const char *aType, + const char *aFileExt) { + nsIMIMEInfo* retval = GetFromType(aType).get(); + PRBool hasDefault = PR_FALSE; + if (retval) + retval->GetHasDefaultHandler(&hasDefault); + if (!retval || !hasDefault) { + nsCOMPtr miByExt = GetFromExtension(aFileExt); + if (!miByExt) + return retval; + if (!retval) { + if (aType) + miByExt->SetMIMEType(aType); + miByExt.swap(retval); + return retval; + } + + // Copy default handler + nsCOMPtr defaultHandler; + nsXPIDLString desc; + miByExt->GetDefaultApplicationHandler(getter_AddRefs(defaultHandler)); + miByExt->GetDefaultDescription(getter_Copies(desc)); + + retval->SetDefaultApplicationHandler(defaultHandler); + retval->SetDefaultDescription(desc.get()); + } + return retval; +} + diff --git a/mozilla/uriloader/exthandler/os2/nsOSHelperAppService.h b/mozilla/uriloader/exthandler/os2/nsOSHelperAppService.h index 78354ee1896..f92751220a2 100644 --- a/mozilla/uriloader/exthandler/os2/nsOSHelperAppService.h +++ b/mozilla/uriloader/exthandler/os2/nsOSHelperAppService.h @@ -31,6 +31,9 @@ #include "nsCExternalHandlerService.h" #include "nsCOMPtr.h" +class nsHashtable; +class nsILineInputStream; + class nsOSHelperAppService : public nsExternalHelperAppService { public: @@ -41,8 +44,7 @@ public: NS_IMETHOD LaunchAppWithTempFile(nsIMIMEInfo *aMIMEInfo, nsIFile * aTempFile); // method overrides for mime.types and mime.info look up steps - nsresult GetMIMEInfoForExtensionFromOS(const char *aFileExt, nsIMIMEInfo **_retval); - nsresult GetMIMEInfoForMimeTypeFromOS(const char *aMIMEType, nsIMIMEInfo **_retval); + already_AddRefed GetMIMEInfoFromOS(const char *aMimeType, const char *aFileExt); // override nsIExternalProtocolService methods NS_IMETHOD ExternalProtocolHandlerExists(const char * aProtocolScheme, PRBool * aHandlerExists); @@ -55,7 +57,78 @@ public: virtual nsresult GetFileTokenForPath(const PRUnichar * platformAppPath, nsIFile ** aFile); protected: + already_AddRefed GetFromType(const char *aMimeType); + already_AddRefed GetFromExtension(const char *aFileExt); +private: + // Helper methods which have to access static members + static nsresult UnescapeCommand(const nsAString& aEscapedCommand, + const nsAString& aMajorType, + const nsAString& aMinorType, + nsHashtable& aTypeOptions, + nsACString& aUnEscapedCommand); + static nsresult GetFileLocation(const char* aPrefName, + const char* aEnvVarName, + PRUnichar** aFileLocation); + static nsresult LookUpTypeAndDescription(const nsAString& aFileExtension, + nsAString& aMajorType, + nsAString& aMinorType, + nsAString& aDescription); + static nsresult CreateInputStream(const nsAString& aFilename, + nsIFileInputStream ** aFileInputStream, + nsILineInputStream ** aLineInputStream, + nsAString& aBuffer, + PRBool * aNetscapeFormat, + PRBool * aMore); + + static nsresult GetTypeAndDescriptionFromMimetypesFile(const nsAString& aFilename, + const nsAString& aFileExtension, + nsAString& aMajorType, + nsAString& aMinorType, + nsAString& aDescription); + + static nsresult LookUpExtensionsAndDescription(const nsAString& aMajorType, + const nsAString& aMinorType, + nsAString& aFileExtensions, + nsAString& aDescription); + + static nsresult GetExtensionsAndDescriptionFromMimetypesFile(const nsAString& aFilename, + const nsAString& aMajorType, + const nsAString& aMinorType, + nsAString& aFileExtensions, + nsAString& aDescription); + + static nsresult ParseNetscapeMIMETypesEntry(const nsAString& aEntry, + nsAString::const_iterator& aMajorTypeStart, + nsAString::const_iterator& aMajorTypeEnd, + nsAString::const_iterator& aMinorTypeStart, + nsAString::const_iterator& aMinorTypeEnd, + nsAString& aExtensions, + nsAString::const_iterator& aDescriptionStart, + nsAString::const_iterator& aDescriptionEnd); + + static nsresult ParseNormalMIMETypesEntry(const nsAString& aEntry, + nsAString::const_iterator& aMajorTypeStart, + nsAString::const_iterator& aMajorTypeEnd, + nsAString::const_iterator& aMinorTypeStart, + nsAString::const_iterator& aMinorTypeEnd, + nsAString& aExtensions, + nsAString::const_iterator& aDescriptionStart, + nsAString::const_iterator& aDescriptionEnd); + + static nsresult LookUpHandlerAndDescription(const nsAString& aMajorType, + const nsAString& aMinorType, + nsHashtable& aTypeOptions, + nsAString& aHandler, + nsAString& aDescription, + nsAString& aMozillaFlags); + static nsresult GetHandlerAndDescriptionFromMailcapFile(const nsAString& aFilename, + const nsAString& aMajorType, + const nsAString& aMinorType, + nsHashtable& aTypeOptions, + nsAString& aHandler, + nsAString& aDescription, + nsAString& aMozillaFlags); }; #endif // nsOSHelperAppService_h__ diff --git a/mozilla/uriloader/exthandler/unix/nsOSHelperAppService.cpp b/mozilla/uriloader/exthandler/unix/nsOSHelperAppService.cpp index 912384dce04..ed8d3274219 100644 --- a/mozilla/uriloader/exthandler/unix/nsOSHelperAppService.cpp +++ b/mozilla/uriloader/exthandler/unix/nsOSHelperAppService.cpp @@ -42,23 +42,9 @@ #include "prenv.h" // for PR_GetEnv() #include // for system() -#ifdef MOZ_LOGGING -#define FORCE_PR_LOG /* Allow logging in the release build */ -#endif /* MOZ_LOGGING */ -#include "prlog.h" +#define LOG(args) PR_LOG(mLog, PR_LOG_DEBUG, args) +#define LOG_ENABLED() PR_LOG_TEST(mLog, PR_LOG_DEBUG) -#ifdef PR_LOGGING -static PRLogModuleInfo *gOSHelperLog = PR_NewLogModule("nsOSHelperAppService"); -#endif /* PR_LOGGING */ - -#define LOG(args) PR_LOG(gOSHelperLog, PR_LOG_DEBUG, args) -#define LOG_ENABLED() PR_LOG_TEST(gOSHelperLog, PR_LOG_DEBUG) -static nsresult -UnescapeCommand(const nsAString& aEscapedCommand, - const nsAString& aMajorType, - const nsAString& aMinorType, - nsHashtable& aTypeOptions, - nsACString& aUnEscapedCommand); static nsresult FindSemicolon(nsAString::const_iterator& aSemicolon_iter, const nsAString::const_iterator& aEnd_iter); @@ -69,83 +55,10 @@ ParseMIMEType(const nsAString::const_iterator& aStart_iter, nsAString::const_iterator& aMinorTypeStart, nsAString::const_iterator& aMinorTypeEnd, const nsAString::const_iterator& aEnd_iter); -static nsresult -GetFileLocation(const char* aPrefName, - const char* aEnvVarName, - PRUnichar** aFileLocation); -static nsresult -LookUpTypeAndDescription(const nsAString& aFileExtension, - nsAString& aMajorType, - nsAString& aMinorType, - nsAString& aDescription); inline PRBool IsNetscapeFormat(const nsAString& aBuffer); -static nsresult -CreateInputStream(const nsAString& aFilename, - nsIFileInputStream** aFileInputStream, - nsILineInputStream** aLineInputStream, - nsAString& aBuffer, - PRBool* aNetscapeFormat, - PRBool* aMore); - -static nsresult -GetTypeAndDescriptionFromMimetypesFile(const nsAString& aFilename, - const nsAString& aFileExtension, - nsAString& aMajorType, - nsAString& aMinorType, - nsAString& aDescription); - -static nsresult -LookUpExtensionsAndDescription(const nsAString& aMajorType, - const nsAString& aMinorType, - nsAString& aFileExtensions, - nsAString& aDescription); -static nsresult -GetExtensionsAndDescriptionFromMimetypesFile(const nsAString& aFilename, - const nsAString& aMajorType, - const nsAString& aMinorType, - nsAString& aFileExtensions, - nsAString& aDescription); - -static nsresult -ParseNetscapeMIMETypesEntry(const nsAString& aEntry, - nsAString::const_iterator& aMajorTypeStart, - nsAString::const_iterator& aMajorTypeEnd, - nsAString::const_iterator& aMinorTypeStart, - nsAString::const_iterator& aMinorTypeEnd, - nsAString& aExtensions, - nsAString::const_iterator& aDescriptionStart, - nsAString::const_iterator& aDescriptionEnd); - - -static nsresult -ParseNormalMIMETypesEntry(const nsAString& aEntry, - nsAString::const_iterator& aMajorTypeStart, - nsAString::const_iterator& aMajorTypeEnd, - nsAString::const_iterator& aMinorTypeStart, - nsAString::const_iterator& aMinorTypeEnd, - nsAString& aExtensions, - nsAString::const_iterator& aDescriptionStart, - nsAString::const_iterator& aDescriptionEnd); - -static nsresult -LookUpHandlerAndDescription(const nsAString& aMajorType, - const nsAString& aMinorType, - nsHashtable& aTypeOptions, - nsAString& aHandler, - nsAString& aDescription, - nsAString& aMozillaFlags); -static nsresult -GetHandlerAndDescriptionFromMailcapFile(const nsAString& aFilename, - const nsAString& aMajorType, - const nsAString& aMinorType, - nsHashtable& aTypeOptions, - nsAString& aHandler, - nsAString& aDescription, - nsAString& aMozillaFlags); - nsOSHelperAppService::nsOSHelperAppService() : nsExternalHelperAppService() { } @@ -207,12 +120,13 @@ NS_IMETHODIMP nsOSHelperAppService::LaunchAppWithTempFile(nsIMIMEInfo * aMIMEInf * Ideally this needs the mime type, mime type options, and location of the * temporary file, but this last can't be got from here */ -static nsresult -UnescapeCommand(const nsAString& aEscapedCommand, - const nsAString& aMajorType, - const nsAString& aMinorType, - nsHashtable& aTypeOptions, - nsACString& aUnEscapedCommand) { +// static +nsresult +nsOSHelperAppService::UnescapeCommand(const nsAString& aEscapedCommand, + const nsAString& aMajorType, + const nsAString& aMinorType, + nsHashtable& aTypeOptions, + nsACString& aUnEscapedCommand) { LOG(("-- UnescapeCommand")); LOG(("Command to escape: '%s'\n", NS_LossyConvertUCS2toASCII(aEscapedCommand).get())); @@ -300,10 +214,11 @@ ParseMIMEType(const nsAString::const_iterator& aStart_iter, return NS_OK; } -static nsresult -GetFileLocation(const char* aPrefName, - const char* aEnvVarName, - PRUnichar** aFileLocation) { +// static +nsresult +nsOSHelperAppService::GetFileLocation(const char* aPrefName, + const char* aEnvVarName, + PRUnichar** aFileLocation) { LOG(("-- GetFileLocation. Pref: '%s' EnvVar: '%s'\n", aPrefName, aEnvVarName)); @@ -375,8 +290,9 @@ GetFileLocation(const char* aPrefName, /* Get the mime.types file names from prefs and look up info in them based on extension */ -static nsresult -LookUpTypeAndDescription(const nsAString& aFileExtension, +// static +nsresult +nsOSHelperAppService::LookUpTypeAndDescription(const nsAString& aFileExtension, nsAString& aMajorType, nsAString& aMinorType, nsAString& aDescription) { @@ -429,13 +345,14 @@ IsNetscapeFormat(const nsAString& aBuffer) { * Leaves the first line of the file in aBuffer and sets the format to * PR_TRUE for netscape files and false for normail ones */ -static nsresult -CreateInputStream(const nsAString& aFilename, - nsIFileInputStream ** aFileInputStream, - nsILineInputStream ** aLineInputStream, - nsAString& aBuffer, - PRBool * aNetscapeFormat, - PRBool * aMore) { +// static +nsresult +nsOSHelperAppService::CreateInputStream(const nsAString& aFilename, + nsIFileInputStream ** aFileInputStream, + nsILineInputStream ** aLineInputStream, + nsAString& aBuffer, + PRBool * aNetscapeFormat, + PRBool * aMore) { LOG(("-- CreateInputStream")); nsresult rv = NS_OK; @@ -478,12 +395,13 @@ CreateInputStream(const nsAString& aFilename, /* Open the file, read the first line, decide what type of file it is, then get info based on extension */ -static nsresult -GetTypeAndDescriptionFromMimetypesFile(const nsAString& aFilename, - const nsAString& aFileExtension, - nsAString& aMajorType, - nsAString& aMinorType, - nsAString& aDescription) { +// static +nsresult +nsOSHelperAppService::GetTypeAndDescriptionFromMimetypesFile(const nsAString& aFilename, + const nsAString& aFileExtension, + nsAString& aMajorType, + nsAString& aMinorType, + nsAString& aDescription) { LOG(("-- GetTypeAndDescriptionFromMimetypesFile\n")); LOG(("Getting type and description from types file '%s'\n", NS_LossyConvertUCS2toASCII(aFilename).get())); @@ -601,11 +519,12 @@ GetTypeAndDescriptionFromMimetypesFile(const nsAString& aFilename, /* Get the mime.types file names from prefs and look up info in them based on mimetype */ -static nsresult -LookUpExtensionsAndDescription(const nsAString& aMajorType, - const nsAString& aMinorType, - nsAString& aFileExtensions, - nsAString& aDescription) { +// static +nsresult +nsOSHelperAppService::LookUpExtensionsAndDescription(const nsAString& aMajorType, + const nsAString& aMinorType, + nsAString& aFileExtensions, + nsAString& aDescription) { LOG(("-- LookUpExtensionsAndDescription for type '%s/%s'\n", NS_LossyConvertUCS2toASCII(aMajorType).get(), NS_LossyConvertUCS2toASCII(aMinorType).get())); @@ -643,12 +562,13 @@ LookUpExtensionsAndDescription(const nsAString& aMajorType, /* Open the file, read the first line, decide what type of file it is, then get info based on extension */ -static nsresult -GetExtensionsAndDescriptionFromMimetypesFile(const nsAString& aFilename, - const nsAString& aMajorType, - const nsAString& aMinorType, - nsAString& aFileExtensions, - nsAString& aDescription) { +// static +nsresult +nsOSHelperAppService::GetExtensionsAndDescriptionFromMimetypesFile(const nsAString& aFilename, + const nsAString& aMajorType, + const nsAString& aMinorType, + nsAString& aFileExtensions, + nsAString& aDescription) { LOG(("-- GetExtensionsAndDescriptionFromMimetypesFile\n")); LOG(("Getting extensions and description from types file '%s'\n", NS_LossyConvertUCS2toASCII(aFilename).get())); @@ -768,15 +688,16 @@ GetExtensionsAndDescriptionFromMimetypesFile(const nsAString& aFilename, * * type=foo/bar; options description="Some type" exts="baz" */ -static nsresult -ParseNetscapeMIMETypesEntry(const nsAString& aEntry, - nsAString::const_iterator& aMajorTypeStart, - nsAString::const_iterator& aMajorTypeEnd, - nsAString::const_iterator& aMinorTypeStart, - nsAString::const_iterator& aMinorTypeEnd, - nsAString& aExtensions, - nsAString::const_iterator& aDescriptionStart, - nsAString::const_iterator& aDescriptionEnd) { +// static +nsresult +nsOSHelperAppService::ParseNetscapeMIMETypesEntry(const nsAString& aEntry, + nsAString::const_iterator& aMajorTypeStart, + nsAString::const_iterator& aMajorTypeEnd, + nsAString::const_iterator& aMinorTypeStart, + nsAString::const_iterator& aMinorTypeEnd, + nsAString& aExtensions, + nsAString::const_iterator& aDescriptionStart, + nsAString::const_iterator& aDescriptionEnd) { LOG(("-- ParseNetscapeMIMETypesEntry\n")); NS_ASSERTION(!aEntry.IsEmpty(), "Empty Netscape MIME types entry being parsed."); @@ -917,15 +838,16 @@ ParseNetscapeMIMETypesEntry(const nsAString& aEntry, * * major/minor ext1 ext2 ext3 */ -static nsresult -ParseNormalMIMETypesEntry(const nsAString& aEntry, - nsAString::const_iterator& aMajorTypeStart, - nsAString::const_iterator& aMajorTypeEnd, - nsAString::const_iterator& aMinorTypeStart, - nsAString::const_iterator& aMinorTypeEnd, - nsAString& aExtensions, - nsAString::const_iterator& aDescriptionStart, - nsAString::const_iterator& aDescriptionEnd) { +// static +nsresult +nsOSHelperAppService::ParseNormalMIMETypesEntry(const nsAString& aEntry, + nsAString::const_iterator& aMajorTypeStart, + nsAString::const_iterator& aMajorTypeEnd, + nsAString::const_iterator& aMinorTypeStart, + nsAString::const_iterator& aMinorTypeEnd, + nsAString& aExtensions, + nsAString::const_iterator& aDescriptionStart, + nsAString::const_iterator& aDescriptionEnd) { LOG(("-- ParseNormalMIMETypesEntry\n")); NS_ASSERTION(!aEntry.IsEmpty(), "Empty Normal MIME types entry being parsed."); @@ -996,13 +918,14 @@ ParseNormalMIMETypesEntry(const nsAString& aEntry, return NS_OK; } -static nsresult -LookUpHandlerAndDescription(const nsAString& aMajorType, - const nsAString& aMinorType, - nsHashtable& aTypeOptions, - nsAString& aHandler, - nsAString& aDescription, - nsAString& aMozillaFlags) { +// static +nsresult +nsOSHelperAppService::LookUpHandlerAndDescription(const nsAString& aMajorType, + const nsAString& aMinorType, + nsHashtable& aTypeOptions, + nsAString& aHandler, + nsAString& aDescription, + nsAString& aMozillaFlags) { LOG(("-- LookUpHandlerAndDescription for type '%s/%s'\n", NS_LossyConvertUCS2toASCII(aMajorType).get(), NS_LossyConvertUCS2toASCII(aMinorType).get())); @@ -1042,14 +965,15 @@ LookUpHandlerAndDescription(const nsAString& aMajorType, return rv; } -static nsresult -GetHandlerAndDescriptionFromMailcapFile(const nsAString& aFilename, - const nsAString& aMajorType, - const nsAString& aMinorType, - nsHashtable& aTypeOptions, - nsAString& aHandler, - nsAString& aDescription, - nsAString& aMozillaFlags) { +// static +nsresult +nsOSHelperAppService::GetHandlerAndDescriptionFromMailcapFile(const nsAString& aFilename, + const nsAString& aMajorType, + const nsAString& aMinorType, + nsHashtable& aTypeOptions, + nsAString& aHandler, + nsAString& aDescription, + nsAString& aMozillaFlags) { LOG(("-- GetHandlerAndDescriptionFromMailcapFile\n")); LOG(("Getting handler and description from mailcap file '%s'\n", @@ -1309,11 +1233,11 @@ nsresult nsOSHelperAppService::GetFileTokenForPath(const PRUnichar * platformApp return rv; } -nsresult nsOSHelperAppService::GetMIMEInfoForExtensionFromOS(const char *aFileExt, - nsIMIMEInfo ** _retval) { +already_AddRefed +nsOSHelperAppService::GetFromExtension(const char *aFileExt) { // if the extension is null, return immediately if (!aFileExt || !*aFileExt) - return NS_ERROR_INVALID_ARG; + return nsnull; LOG(("Here we do an extension lookup for '%s'\n", aFileExt)); @@ -1328,7 +1252,7 @@ nsresult nsOSHelperAppService::GetMIMEInfoForExtensionFromOS(const char *aFileEx minorType, mime_types_description); if (NS_FAILED(rv)) - return rv; + return nsnull; LOG(("Type/Description results: majorType='%s', minorType='%s', description='%s'\n", NS_LossyConvertUCS2toASCII(majorType).get(), @@ -1337,12 +1261,13 @@ nsresult nsOSHelperAppService::GetMIMEInfoForExtensionFromOS(const char *aFileEx if (majorType.IsEmpty() && minorType.IsEmpty()) { // we didn't get a type mapping, so we can't do anything useful - return NS_ERROR_FAILURE; + return nsnull; } - nsCOMPtr mimeInfo(do_CreateInstance(NS_MIMEINFO_CONTRACTID, &rv)); + nsIMIMEInfo* mimeInfo = nsnull; + rv = CallCreateInstance(NS_MIMEINFO_CONTRACTID, &mimeInfo); if (NS_FAILED(rv)) - return rv; + return nsnull; mimeType = majorType + NS_LITERAL_STRING("/") + minorType; mimeInfo->SetMIMEType(NS_ConvertUCS2toUTF8(mimeType).get()); @@ -1389,21 +1314,19 @@ nsresult nsOSHelperAppService::GetMIMEInfoForExtensionFromOS(const char *aFileEx } else { mimeInfo->SetPreferredAction(nsIMIMEInfo::saveToDisk); } - - *_retval = mimeInfo; - NS_ADDREF(*_retval); + + return mimeInfo; // XXX Once cache can be invalidated, add the mime info to it. See bug 121644 // AddMimeInfoToCache(*_retval); - - return NS_OK; + } -nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char *aMIMEType, - nsIMIMEInfo ** _retval) { +already_AddRefed +nsOSHelperAppService::GetFromType(const char *aMIMEType) { // if the extension is null, return immediately if (!aMIMEType) - return NS_ERROR_INVALID_ARG; + return nsnull; LOG(("Here we do a mimetype lookup for '%s'\n", aMIMEType)); nsresult rv; @@ -1428,7 +1351,7 @@ nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char *aMIMETyp minorTypeStart, minorTypeEnd, end_iter); if (NS_FAILED(rv)) { - return rv; + return nsnull; } nsDependentSubstring majorType(majorTypeStart, majorTypeEnd); @@ -1464,7 +1387,7 @@ nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char *aMIMETyp if (handler.IsEmpty()) { // we have no useful info.... - return NS_ERROR_FAILURE; + return nsnull; } mailcap_description.Trim(" \t\""); @@ -1473,12 +1396,12 @@ nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char *aMIMETyp minorType, extensions, mime_types_description); - - nsCOMPtr mimeInfo(do_CreateInstance(NS_MIMEINFO_CONTRACTID, &rv)); - + + nsIMIMEInfo* mimeInfo = nsnull; + rv = CallCreateInstance(NS_MIMEINFO_CONTRACTID, &mimeInfo); if (NS_FAILED(rv)) - return rv; - + return nsnull; + mimeInfo->SetFileExtensions(PromiseFlatCString(NS_ConvertUCS2toUTF8(extensions)).get()); mimeInfo->SetMIMEType(aMIMEType); if (! mime_types_description.IsEmpty()) { @@ -1486,7 +1409,7 @@ nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char *aMIMETyp } else { mimeInfo->SetDescription(mailcap_description.get()); } - + rv = NS_ERROR_FAILURE; nsCOMPtr handlerFile; rv = GetFileTokenForPath(handler.get(), getter_AddRefs(handlerFile)); @@ -1498,11 +1421,38 @@ nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char *aMIMETyp } else { mimeInfo->SetPreferredAction(nsIMIMEInfo::saveToDisk); } - - *_retval = mimeInfo; - NS_ADDREF(*_retval); - - // XXX Once cache can be invalidated, add the mime info to it. See bug 121644 - // AddMimeInfoToCache(*_retval); - return NS_OK; + + return mimeInfo; } + + +already_AddRefed +nsOSHelperAppService::GetMIMEInfoFromOS(const char *aType, + const char *aFileExt) { + nsIMIMEInfo* retval = GetFromType(aType).get(); + PRBool hasDefault = PR_FALSE; + if (retval) + retval->GetHasDefaultHandler(&hasDefault); + if (!retval || !hasDefault) { + nsCOMPtr miByExt = GetFromExtension(aFileExt); + if (!miByExt) + return retval; + if (!retval) { + if (aType) + miByExt->SetMIMEType(aType); + miByExt.swap(retval); + return retval; + } + + // Copy default handler + nsCOMPtr defaultHandler; + nsXPIDLString desc; + miByExt->GetDefaultApplicationHandler(getter_AddRefs(defaultHandler)); + miByExt->GetDefaultDescription(getter_Copies(desc)); + + retval->SetDefaultApplicationHandler(defaultHandler); + retval->SetDefaultDescription(desc.get()); + } + return retval; +} + diff --git a/mozilla/uriloader/exthandler/unix/nsOSHelperAppService.h b/mozilla/uriloader/exthandler/unix/nsOSHelperAppService.h index 78354ee1896..f92751220a2 100644 --- a/mozilla/uriloader/exthandler/unix/nsOSHelperAppService.h +++ b/mozilla/uriloader/exthandler/unix/nsOSHelperAppService.h @@ -31,6 +31,9 @@ #include "nsCExternalHandlerService.h" #include "nsCOMPtr.h" +class nsHashtable; +class nsILineInputStream; + class nsOSHelperAppService : public nsExternalHelperAppService { public: @@ -41,8 +44,7 @@ public: NS_IMETHOD LaunchAppWithTempFile(nsIMIMEInfo *aMIMEInfo, nsIFile * aTempFile); // method overrides for mime.types and mime.info look up steps - nsresult GetMIMEInfoForExtensionFromOS(const char *aFileExt, nsIMIMEInfo **_retval); - nsresult GetMIMEInfoForMimeTypeFromOS(const char *aMIMEType, nsIMIMEInfo **_retval); + already_AddRefed GetMIMEInfoFromOS(const char *aMimeType, const char *aFileExt); // override nsIExternalProtocolService methods NS_IMETHOD ExternalProtocolHandlerExists(const char * aProtocolScheme, PRBool * aHandlerExists); @@ -55,7 +57,78 @@ public: virtual nsresult GetFileTokenForPath(const PRUnichar * platformAppPath, nsIFile ** aFile); protected: + already_AddRefed GetFromType(const char *aMimeType); + already_AddRefed GetFromExtension(const char *aFileExt); +private: + // Helper methods which have to access static members + static nsresult UnescapeCommand(const nsAString& aEscapedCommand, + const nsAString& aMajorType, + const nsAString& aMinorType, + nsHashtable& aTypeOptions, + nsACString& aUnEscapedCommand); + static nsresult GetFileLocation(const char* aPrefName, + const char* aEnvVarName, + PRUnichar** aFileLocation); + static nsresult LookUpTypeAndDescription(const nsAString& aFileExtension, + nsAString& aMajorType, + nsAString& aMinorType, + nsAString& aDescription); + static nsresult CreateInputStream(const nsAString& aFilename, + nsIFileInputStream ** aFileInputStream, + nsILineInputStream ** aLineInputStream, + nsAString& aBuffer, + PRBool * aNetscapeFormat, + PRBool * aMore); + + static nsresult GetTypeAndDescriptionFromMimetypesFile(const nsAString& aFilename, + const nsAString& aFileExtension, + nsAString& aMajorType, + nsAString& aMinorType, + nsAString& aDescription); + + static nsresult LookUpExtensionsAndDescription(const nsAString& aMajorType, + const nsAString& aMinorType, + nsAString& aFileExtensions, + nsAString& aDescription); + + static nsresult GetExtensionsAndDescriptionFromMimetypesFile(const nsAString& aFilename, + const nsAString& aMajorType, + const nsAString& aMinorType, + nsAString& aFileExtensions, + nsAString& aDescription); + + static nsresult ParseNetscapeMIMETypesEntry(const nsAString& aEntry, + nsAString::const_iterator& aMajorTypeStart, + nsAString::const_iterator& aMajorTypeEnd, + nsAString::const_iterator& aMinorTypeStart, + nsAString::const_iterator& aMinorTypeEnd, + nsAString& aExtensions, + nsAString::const_iterator& aDescriptionStart, + nsAString::const_iterator& aDescriptionEnd); + + static nsresult ParseNormalMIMETypesEntry(const nsAString& aEntry, + nsAString::const_iterator& aMajorTypeStart, + nsAString::const_iterator& aMajorTypeEnd, + nsAString::const_iterator& aMinorTypeStart, + nsAString::const_iterator& aMinorTypeEnd, + nsAString& aExtensions, + nsAString::const_iterator& aDescriptionStart, + nsAString::const_iterator& aDescriptionEnd); + + static nsresult LookUpHandlerAndDescription(const nsAString& aMajorType, + const nsAString& aMinorType, + nsHashtable& aTypeOptions, + nsAString& aHandler, + nsAString& aDescription, + nsAString& aMozillaFlags); + static nsresult GetHandlerAndDescriptionFromMailcapFile(const nsAString& aFilename, + const nsAString& aMajorType, + const nsAString& aMinorType, + nsHashtable& aTypeOptions, + nsAString& aHandler, + nsAString& aDescription, + nsAString& aMozillaFlags); }; #endif // nsOSHelperAppService_h__ diff --git a/mozilla/uriloader/exthandler/win/nsOSHelperAppService.cpp b/mozilla/uriloader/exthandler/win/nsOSHelperAppService.cpp index 21f1085bb8e..ebd217b2a58 100644 --- a/mozilla/uriloader/exthandler/win/nsOSHelperAppService.cpp +++ b/mozilla/uriloader/exthandler/win/nsOSHelperAppService.cpp @@ -30,6 +30,7 @@ #include "nsILocalFile.h" #include "nsIProcess.h" #include "plstr.h" +#include "nsAutoPtr.h" // we need windows.h to read out registry information... #include @@ -37,6 +38,8 @@ // shellapi.h is needed to build with WIN32_LEAN_AND_MEAN #include +#define LOG(args) PR_LOG(mLog, PR_LOG_DEBUG, args) + // helper methods: forward declarations... BYTE * GetValueBytes( HKEY hKey, const char *pValueName, DWORD *pLen=0); nsresult GetExtensionFrom4xRegistryInfo(const char * aMimeType, nsCString& aFileExtension); @@ -296,79 +299,104 @@ static nsresult GetMIMEInfoFromRegistry( LPBYTE fileType, nsIMIMEInfo *pInfo ) // method overrides used to gather information from the windows registry for // various mime types. //////////////////////////////////////////////////////////////////////////////////////////////// -nsresult nsOSHelperAppService::GetMIMEInfoForExtensionFromOS(const char *aFileExt, nsIMIMEInfo **_retval) -{ - if (!aFileExt || !*aFileExt) return NS_ERROR_FAILURE; - nsresult rv = NS_OK; +/// Looks up the type for the extension aExt and compares it to aType +static PRBool typeFromExtEquals(const char *aExt, const char *aType) +{ + if (!aType) + return PR_FALSE; + nsCAutoString fileExtToUse; + if (aExt[0] != '.') + fileExtToUse = '.'; + + fileExtToUse.Append(aExt); + + HKEY hKey; + LONG err = ::RegOpenKeyEx( HKEY_CLASSES_ROOT, fileExtToUse.get(), 0, KEY_QUERY_VALUE, &hKey); + if (err == ERROR_SUCCESS) + { + LPBYTE pBytes = GetValueBytes( hKey, "Content Type"); + PRBool eq = strcmp((const char *)pBytes, aType) == 0; + delete[] pBytes; + return eq; + } + return PR_FALSE; +} + +already_AddRefed nsOSHelperAppService::GetByExtension(const char *aFileExt, const char *aTypeHint) +{ + if (!aFileExt || !*aFileExt) + return nsnull; // windows registry assumes your file extension is going to include the '.'. // so make sure it's there... nsCAutoString fileExtToUse; - if (aFileExt && aFileExt[0] != '.') + if (*aFileExt != '.') fileExtToUse = '.'; fileExtToUse.Append(aFileExt); // o.t. try to get an entry from the windows registry. - HKEY hKey; - LONG err = ::RegOpenKeyEx( HKEY_CLASSES_ROOT, fileExtToUse.get(), 0, KEY_QUERY_VALUE, &hKey); - if (err == ERROR_SUCCESS) - { + HKEY hKey; + LONG err = ::RegOpenKeyEx( HKEY_CLASSES_ROOT, fileExtToUse.get(), 0, KEY_QUERY_VALUE, &hKey); + if (err == ERROR_SUCCESS) + { + nsCAutoString typeToUse; + if (aTypeHint) { + typeToUse.Assign(aTypeHint); + } + else { LPBYTE pBytes = GetValueBytes( hKey, "Content Type"); - LPBYTE pFileDescription = GetValueBytes(hKey, ""); - - nsCOMPtr mimeInfo (do_CreateInstance(NS_MIMEINFO_CONTRACTID)); - if (mimeInfo && pBytes) - { - mimeInfo->SetMIMEType((char *) pBytes); - // if the file extension includes the '.' then we don't want to include that when we append - // it to the mime info object. - if (aFileExt && *aFileExt == '.' && (aFileExt+1)) - mimeInfo->AppendExtension(aFileExt+1); - else - mimeInfo->AppendExtension(aFileExt); - - mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault); - - nsAutoString description; - description.AssignWithConversion((char *) pFileDescription); - - PRInt32 pos = description.FindChar('.'); - if (pos > 0) - description.Truncate(pos); - // the format of the description usually looks like appname.version.something. - // for now, let's try to make it pretty and just show you the appname. - - mimeInfo->SetDefaultDescription(description.get()); - - // Get other nsIMIMEInfo fields from registry, if possible. - if ( pFileDescription ) - { - GetMIMEInfoFromRegistry( pFileDescription, mimeInfo ); - } - - // if we got here, then set our return variable - *_retval = mimeInfo; - NS_ADDREF(*_retval); - } - else - rv = NS_ERROR_FAILURE; // we failed to really find an entry in the registry - + if (pBytes) + typeToUse.Assign((const char*)pBytes); delete [] pBytes; - delete [] pFileDescription; + } + LPBYTE pFileDescription = GetValueBytes(hKey, ""); - // close the key - ::RegCloseKey(hKey); - } + nsIMIMEInfo* mimeInfo = nsnull; + CallCreateInstance(NS_MIMEINFO_CONTRACTID, &mimeInfo); + if (mimeInfo && !typeToUse.IsEmpty()) + { + mimeInfo->SetMIMEType(typeToUse.get()); + // don't append the '.' + mimeInfo->AppendExtension(fileExtToUse.get() + 1); - // we failed to find a mime type. - if (!*_retval) rv = NS_ERROR_FAILURE; - - return rv; + mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault); + + nsAutoString description; + description.AssignWithConversion((char *) pFileDescription); + + PRInt32 pos = description.FindChar('.'); + if (pos > 0) + description.Truncate(pos); + // the format of the description usually looks like appname.version.something. + // for now, let's try to make it pretty and just show you the appname. + + mimeInfo->SetDefaultDescription(description.get()); + + // Get other nsIMIMEInfo fields from registry, if possible. + if ( pFileDescription ) + { + GetMIMEInfoFromRegistry( pFileDescription, mimeInfo ); + } + } + else { + NS_IF_RELEASE(mimeInfo); // we failed to really find an entry in the registry + } + + delete [] pFileDescription; + + // close the key + ::RegCloseKey(hKey); + + return mimeInfo; + } + + // we failed to find a mime type. + return nsnull; } -nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char *aMIMEType, nsIMIMEInfo ** _retval) +already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS(const char *aMIMEType, const char *aFileExt) { if (PL_strcasecmp(aMIMEType, APPLICATION_OCTET_STREAM) == 0) { /* XXX Gross hack to wallpaper over the most common Win32 @@ -377,20 +405,66 @@ nsresult nsOSHelperAppService::GetMIMEInfoForMimeTypeFromOS(const char *aMIMETyp * want to remove this once we have fixed all this stuff to work * right; any info we get from the OS on this type is pretty much * useless.... + * Just lookup by extension for this filetype. */ - return NS_ERROR_FAILURE; + aMIMEType = nsnull; + // If we now have nothing to lookup from, return + if (!aFileExt || !*aFileExt) + return nsnull; } - - // (1) try to use the windows mime database to see if there is a mapping to a file extension - // (2) try to see if we have some left over 4.x registry info we can peek at... + nsCAutoString fileExtension; - GetExtensionFromWindowsMimeDatabase(aMIMEType, fileExtension); - if (fileExtension.IsEmpty()) - GetExtensionFrom4xRegistryInfo(aMIMEType, fileExtension); - - // now look up based on the file extension. + if (aMIMEType && *aMIMEType) { + // (1) try to use the windows mime database to see if there is a mapping to a file extension + // (2) try to see if we have some left over 4.x registry info we can peek at... + GetExtensionFromWindowsMimeDatabase(aMIMEType, fileExtension); + LOG(("Windows mime database: extension '%s'\n", fileExtension.get())); + if (fileExtension.IsEmpty()) { + GetExtensionFrom4xRegistryInfo(aMIMEType, fileExtension); + LOG(("4.x Registry: extension '%s'\n", fileExtension.get())); + } + } + // If we found an extension for the type, do the lookup + nsIMIMEInfo* mi = nsnull; if (!fileExtension.IsEmpty()) - return GetFromExtension(fileExtension.get(), _retval); + mi = GetByExtension(fileExtension.get(), aMIMEType).get(); + LOG(("Extension lookup on '%s' found: 0x%p\n", fileExtension.get(), mi)); - return NS_ERROR_FAILURE; + PRBool hasDefault = PR_FALSE; + if (mi) { + mi->GetHasDefaultHandler(&hasDefault); + // OK. We might have the case that |aFileExt| is a valid extension for the + // mimetype we were given. In that case, we do want to append aFileExt + // to the mimeinfo that we have. (E.g.: We are asked for video/mpeg and + // .mpg, but the primary extension for video/mpeg is .mpeg. But because + // .mpg is an extension for video/mpeg content, we want to append it) + if (aFileExt && *aFileExt && typeFromExtEquals(aFileExt, aMIMEType)) { + LOG(("Appending extension '%s' to mimeinfo, because its mimetype is '%s'\n", + aFileExt, aMIMEType)); + PRBool extExist = PR_FALSE; + mi->ExtensionExists(aFileExt, &extExist); + if (!extExist) + mi->AppendExtension(aFileExt); + } + } + if (!mi || !hasDefault) { + nsCOMPtr miByExt = GetByExtension(aFileExt, aMIMEType); + LOG(("Ext. lookup for '%s' found 0x%p\n", aFileExt, miByExt.get())); + if (!miByExt) + return mi; + if (!mi) { + miByExt.swap(mi); + return mi; + } + + // if we get here, mi has no default app. copy from extension lookup. + nsCOMPtr defaultApp; + nsXPIDLString desc; + miByExt->GetDefaultApplicationHandler(getter_AddRefs(defaultApp)); + miByExt->GetDefaultDescription(getter_Copies(desc)); + + mi->SetDefaultApplicationHandler(defaultApp); + mi->SetDefaultDescription(desc.get()); + } + return mi; } diff --git a/mozilla/uriloader/exthandler/win/nsOSHelperAppService.h b/mozilla/uriloader/exthandler/win/nsOSHelperAppService.h index b32711cdd26..126f43621a2 100644 --- a/mozilla/uriloader/exthandler/win/nsOSHelperAppService.h +++ b/mozilla/uriloader/exthandler/win/nsOSHelperAppService.h @@ -45,8 +45,7 @@ public: NS_IMETHOD LoadUrl(nsIURI * aURL); // method overrides for windows registry look up steps.... - nsresult GetMIMEInfoForExtensionFromOS(const char *aFileExt, nsIMIMEInfo **_retval); - nsresult GetMIMEInfoForMimeTypeFromOS(const char *aMIMEType, nsIMIMEInfo ** _retval); + already_AddRefed GetMIMEInfoFromOS(const char *aMIMEType, const char *aFileExt); // GetFileTokenForPath must be implemented by each platform. // platformAppPath --> a platform specific path to an application that we got out of the @@ -55,6 +54,8 @@ public: virtual nsresult GetFileTokenForPath(const PRUnichar * platformAppPath, nsIFile ** aFile); protected: + // Lookup a mime info by extension, using an optional type hint + already_AddRefed GetByExtension(const char *aFileExt, const char *aTypeHint = nsnull); nsresult FindOSMimeInfoForType(const char * aMimeContentType, nsIURI * aURI, char ** aFileExtension, nsIMIMEInfo ** aMIMEInfo); }; diff --git a/mozilla/xpfe/communicator/resources/content/contentAreaUtils.js b/mozilla/xpfe/communicator/resources/content/contentAreaUtils.js index b8943bcb51e..ee441fe9b83 100644 --- a/mozilla/xpfe/communicator/resources/content/contentAreaUtils.js +++ b/mozilla/xpfe/communicator/resources/content/contentAreaUtils.js @@ -736,7 +736,7 @@ function getMIMEService() function getMIMEInfoForExtension(aExtension) { try { - return getMIMEService().GetFromExtension(aExtension); + return getMIMEService().GetFromTypeAndExtension(null, aExtension); } catch (e) { } @@ -746,7 +746,7 @@ function getMIMEInfoForExtension(aExtension) function getMIMEInfoForType(aMIMEType) { try { - return getMIMEService().GetFromMIMEType(aMIMEType); + return getMIMEService().GetFromTypeAndExtension(aMIMEType, null); } catch (e) { }