diff --git a/docshell/build/components.conf b/docshell/build/components.conf index f8c3e248f2ca..f3dd9532e64b 100644 --- a/docshell/build/components.conf +++ b/docshell/build/components.conf @@ -71,8 +71,9 @@ Classes = [ '@mozilla.org/uriloader/external-helper-app-service;1', '@mozilla.org/uriloader/external-protocol-service;1', ], - 'type': 'nsOSHelperAppService', - 'headers': ['nsOSHelperAppService.h'], + 'type': 'nsExternalHelperAppService', + 'constructor': 'nsExternalHelperAppService::GetSingleton', + 'headers': ['nsExternalHelperAppService.h'], 'init_method': 'Init', 'processes': ProcessSelector.ALLOW_IN_SOCKET_PROCESS, }, diff --git a/ipc/ipdl/sync-messages.ini b/ipc/ipdl/sync-messages.ini index fad32c2470ca..094941ace88b 100644 --- a/ipc/ipdl/sync-messages.ini +++ b/ipc/ipdl/sync-messages.ini @@ -1049,12 +1049,18 @@ description = description = [PHandlerService::FillHandlerInfo] description = -[PHandlerService::ExistsForProtocol] +[PHandlerService::GetMIMEInfoFromOS] +description = Lets unprivileged child processes synchronously get MIME type/handler information from the OS +[PHandlerService::ExistsForProtocolOS] description = bug 1382323 +[PHandlerService::ExistsForProtocol] +description = [PHandlerService::Exists] description = [PHandlerService::GetTypeFromExtension] description = +[PHandlerService::GetApplicationDescription] +description = Lets unprivileged child processes synchronously get a description of the app that handles a given protocol scheme [PLayerTransaction::ShutdownSync] description = bug 1363126 [PClientSource::WorkerSyncPing] diff --git a/netwerk/mime/nsIMIMEService.idl b/netwerk/mime/nsIMIMEService.idl index 704269c3cda9..a2faa0ff56e7 100644 --- a/netwerk/mime/nsIMIMEService.idl +++ b/netwerk/mime/nsIMIMEService.idl @@ -72,4 +72,29 @@ interface nsIMIMEService : nsISupports { * @param aFileExt File Extension. Can be empty. */ AUTF8String getPrimaryExtension(in ACString aMIMEType, in AUTF8String aFileExt); + + /* + * Returns an nsIMIMEInfo for the provided MIME type and extension + * obtained from an OS lookup. If no handler is found for the type and + * extension, returns a generic nsIMIMEInfo object. The MIME type and + * extension can be the empty string. When the type and extension don't + * map to the same handler, the semantics/resolution are platform + * specific. See the platform implementations for details. + * + * @param aType The MIME type to get handler information for. + * @param aFileExtension The filename extension to use either alone + * or with the MIME type to get handler information + * for. UTF-8 encoded. + * @param [out] aFound Out param indicating whether a MIMEInfo could + * be found for the provided type and/or extension. + * Set to false when neither extension nor the MIME + * type are mapped to a handler. + * @return A nsIMIMEInfo object. This function must return + * a MIMEInfo object if it can allocate one. The + * only justifiable reason for not returning one is + * an out-of-memory error. + */ + nsIMIMEInfo getMIMEInfoFromOS(in ACString aType, + in ACString aFileExtension, + out boolean aFound); }; diff --git a/uriloader/exthandler/ContentHandlerService.cpp b/uriloader/exthandler/ContentHandlerService.cpp index f199ad461bac..7e2d53fc9832 100644 --- a/uriloader/exthandler/ContentHandlerService.cpp +++ b/uriloader/exthandler/ContentHandlerService.cpp @@ -166,6 +166,25 @@ NS_IMETHODIMP ContentHandlerService::FillHandlerInfo( return NS_OK; } +NS_IMETHODIMP ContentHandlerService::GetMIMEInfoFromOS( + nsIHandlerInfo* aHandlerInfo, const nsACString& aMIMEType, + const nsACString& aExtension, bool* aFound) { + nsresult rv = NS_ERROR_FAILURE; + HandlerInfo returnedInfo; + if (!mHandlerServiceChild->SendGetMIMEInfoFromOS(nsCString(aMIMEType), + nsCString(aExtension), &rv, + &returnedInfo, aFound)) { + return NS_ERROR_FAILURE; + } + + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + CopyHanderInfoTonsIHandlerInfo(returnedInfo, aHandlerInfo); + return NS_OK; +} + NS_IMETHODIMP ContentHandlerService::Store(nsIHandlerInfo* aHandlerInfo) { return NS_ERROR_NOT_IMPLEMENTED; } @@ -182,6 +201,16 @@ NS_IMETHODIMP ContentHandlerService::Remove(nsIHandlerInfo* aHandlerInfo) { return NS_ERROR_NOT_IMPLEMENTED; } +NS_IMETHODIMP +ContentHandlerService::ExistsForProtocolOS(const nsACString& aProtocolScheme, + bool* aRetval) { + if (!mHandlerServiceChild->SendExistsForProtocolOS(nsCString(aProtocolScheme), + aRetval)) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + NS_IMETHODIMP ContentHandlerService::ExistsForProtocol(const nsACString& aProtocolScheme, bool* aRetval) { @@ -208,5 +237,15 @@ NS_IMETHODIMP ContentHandlerService::GetTypeFromExtension( return NS_OK; } +NS_IMETHODIMP ContentHandlerService::GetApplicationDescription( + const nsACString& aProtocolScheme, nsAString& aRetVal) { + nsresult rv = NS_ERROR_FAILURE; + nsAutoCString scheme(aProtocolScheme); + nsAutoString desc; + mHandlerServiceChild->SendGetApplicationDescription(scheme, &rv, &desc); + aRetVal.Assign(desc); + return rv; +} + } // namespace dom } // namespace mozilla diff --git a/uriloader/exthandler/HandlerServiceParent.cpp b/uriloader/exthandler/HandlerServiceParent.cpp index 6f4c7909d1c8..b3c20733732b 100644 --- a/uriloader/exthandler/HandlerServiceParent.cpp +++ b/uriloader/exthandler/HandlerServiceParent.cpp @@ -1,3 +1,4 @@ +#include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/Logging.h" #include "HandlerServiceParent.h" #include "nsIHandlerService.h" @@ -238,6 +239,31 @@ mozilla::ipc::IPCResult HandlerServiceParent::RecvFillHandlerInfo( return IPC_OK(); } +mozilla::ipc::IPCResult HandlerServiceParent::RecvGetMIMEInfoFromOS( + const nsCString& aMIMEType, const nsCString& aExtension, nsresult* aRv, + HandlerInfo* aHandlerInfoData, bool* aFound) { + *aFound = false; + nsCOMPtr mimeService = + do_GetService(NS_MIMESERVICE_CONTRACTID, aRv); + if (NS_WARN_IF(NS_FAILED(*aRv))) { + return IPC_OK(); + } + + nsCOMPtr mimeInfo; + *aRv = mimeService->GetMIMEInfoFromOS(aMIMEType, aExtension, aFound, + getter_AddRefs(mimeInfo)); + if (NS_WARN_IF(NS_FAILED(*aRv))) { + return IPC_OK(); + } + + if (mimeInfo) { + ContentHandlerService::nsIHandlerInfoToHandlerInfo(mimeInfo, + aHandlerInfoData); + } + + return IPC_OK(); +} + mozilla::ipc::IPCResult HandlerServiceParent::RecvExists( const HandlerInfo& aHandlerInfo, bool* exists) { nsCOMPtr info(WrapHandlerInfo(aHandlerInfo)); @@ -247,7 +273,7 @@ mozilla::ipc::IPCResult HandlerServiceParent::RecvExists( return IPC_OK(); } -mozilla::ipc::IPCResult HandlerServiceParent::RecvExistsForProtocol( +mozilla::ipc::IPCResult HandlerServiceParent::RecvExistsForProtocolOS( const nsCString& aProtocolScheme, bool* aHandlerExists) { #ifdef MOZ_WIDGET_GTK // Check the GNOME registry for a protocol handler @@ -258,11 +284,56 @@ mozilla::ipc::IPCResult HandlerServiceParent::RecvExistsForProtocol( return IPC_OK(); } +/* + * Check if a handler exists for the provided protocol. Check the datastore + * first and then fallback to checking the OS for a handler. + */ +mozilla::ipc::IPCResult HandlerServiceParent::RecvExistsForProtocol( + const nsCString& aProtocolScheme, bool* aHandlerExists) { +#if defined(XP_MACOSX) + // Check the datastore and fallback to an OS check. + // ExternalProcotolHandlerExists() does the fallback. + nsresult rv; + nsCOMPtr protoSvc = + do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID, &rv); + if (NS_WARN_IF(NS_FAILED(rv))) { + *aHandlerExists = false; + return IPC_OK(); + } + rv = protoSvc->ExternalProtocolHandlerExists(aProtocolScheme.get(), + aHandlerExists); + + if (NS_WARN_IF(NS_FAILED(rv))) { + *aHandlerExists = false; + } +#else + MOZ_RELEASE_ASSERT(false, "No implementation on this platform."); + *aHandlerExists = false; +#endif + return IPC_OK(); +} + mozilla::ipc::IPCResult HandlerServiceParent::RecvGetTypeFromExtension( const nsCString& aFileExtension, nsCString* type) { + nsresult rv; nsCOMPtr handlerSvc = - do_GetService(NS_HANDLERSERVICE_CONTRACTID); - handlerSvc->GetTypeFromExtension(aFileExtension, *type); + do_GetService(NS_HANDLERSERVICE_CONTRACTID, &rv); + if (NS_WARN_IF(NS_FAILED(rv))) { + return IPC_OK(); + } + + rv = handlerSvc->GetTypeFromExtension(aFileExtension, *type); + mozilla::Unused << NS_WARN_IF(NS_FAILED(rv)); + + return IPC_OK(); +} + +mozilla::ipc::IPCResult HandlerServiceParent::RecvGetApplicationDescription( + const nsCString& aScheme, nsresult* aRv, nsString* aDescription) { + nsCOMPtr protoSvc = + do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID); + NS_ASSERTION(protoSvc, "No Helper App Service!"); + *aRv = protoSvc->GetApplicationDescription(aScheme, *aDescription); return IPC_OK(); } diff --git a/uriloader/exthandler/HandlerServiceParent.h b/uriloader/exthandler/HandlerServiceParent.h index f06d531f7a29..a4d0dc419467 100644 --- a/uriloader/exthandler/HandlerServiceParent.h +++ b/uriloader/exthandler/HandlerServiceParent.h @@ -13,19 +13,32 @@ class HandlerServiceParent final : public mozilla::dom::PHandlerServiceParent { private: virtual ~HandlerServiceParent(); - virtual void ActorDestroy(ActorDestroyReason aWhy) override; + void ActorDestroy(ActorDestroyReason aWhy) override; - virtual mozilla::ipc::IPCResult RecvFillHandlerInfo( + mozilla::ipc::IPCResult RecvFillHandlerInfo( const HandlerInfo& aHandlerInfoData, const nsCString& aOverrideType, HandlerInfo* handlerInfoData) override; - virtual mozilla::ipc::IPCResult RecvExists(const HandlerInfo& aHandlerInfo, - bool* exits) override; - virtual mozilla::ipc::IPCResult RecvGetTypeFromExtension( + mozilla::ipc::IPCResult RecvGetMIMEInfoFromOS(const nsCString& aMIMEType, + const nsCString& aExtension, + nsresult* aRv, + HandlerInfo* aHandlerInfoData, + bool* aFound) override; + + mozilla::ipc::IPCResult RecvExists(const HandlerInfo& aHandlerInfo, + bool* exists) override; + + mozilla::ipc::IPCResult RecvGetTypeFromExtension( const nsCString& aFileExtension, nsCString* type) override; - virtual mozilla::ipc::IPCResult RecvExistsForProtocol( + mozilla::ipc::IPCResult RecvExistsForProtocolOS( const nsCString& aProtocolScheme, bool* aHandlerExists) override; + + mozilla::ipc::IPCResult RecvExistsForProtocol( + const nsCString& aProtocolScheme, bool* aHandlerExists) override; + + mozilla::ipc::IPCResult RecvGetApplicationDescription( + const nsCString& aScheme, nsresult* aRv, nsString* aDescription) override; }; #endif diff --git a/uriloader/exthandler/PHandlerService.ipdl b/uriloader/exthandler/PHandlerService.ipdl index 91af9001864b..5d5ba779902b 100644 --- a/uriloader/exthandler/PHandlerService.ipdl +++ b/uriloader/exthandler/PHandlerService.ipdl @@ -31,12 +31,28 @@ parent: sync FillHandlerInfo(HandlerInfo aHandlerInfoData, nsCString aOverrideType) returns (HandlerInfo handlerInfoData); + + /* + * Check if an OS handler exists for the given protocol scheme. + */ + sync ExistsForProtocolOS(nsCString aProtocolScheme) + returns (bool exists); + + /* + * Check if a handler exists for the given protocol scheme. Check + * the datastore first and then fallback to an OS handler check. + */ sync ExistsForProtocol(nsCString aProtocolScheme) returns (bool exists); + sync Exists(HandlerInfo aHandlerInfo) returns (bool exists); sync GetTypeFromExtension(nsCString aFileExtension) returns (nsCString type); + sync GetMIMEInfoFromOS(nsCString aMIMEType, nsCString aExtension) + returns (nsresult rv, HandlerInfo handlerInfoData, bool found); + sync GetApplicationDescription(nsCString aScheme) + returns (nsresult rv, nsString description); async __delete__(); }; diff --git a/uriloader/exthandler/android/nsOSHelperAppService.cpp b/uriloader/exthandler/android/nsOSHelperAppService.cpp index 0f1f816e2181..6503830e90f4 100644 --- a/uriloader/exthandler/android/nsOSHelperAppService.cpp +++ b/uriloader/exthandler/android/nsOSHelperAppService.cpp @@ -11,8 +11,10 @@ nsOSHelperAppService::nsOSHelperAppService() : nsExternalHelperAppService() {} nsOSHelperAppService::~nsOSHelperAppService() {} -already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS( - const nsACString& aMIMEType, const nsACString& aFileExt, bool* aFound) { +nsresult nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType, + const nsACString& aFileExt, + bool* aFound, + nsIMIMEInfo** aMIMEInfo) { RefPtr mimeInfo; *aFound = false; if (!aMIMEType.IsEmpty()) @@ -26,7 +28,8 @@ already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS( // something for us, so we return the empty object. if (!*aFound) mimeInfo = new nsMIMEInfoAndroid(aMIMEType); - return mimeInfo.forget(); + mimeInfo.forget(aMIMEInfo); + return NS_OK; } nsresult nsOSHelperAppService::OSProtocolHandlerExists(const char* aScheme, diff --git a/uriloader/exthandler/android/nsOSHelperAppService.h b/uriloader/exthandler/android/nsOSHelperAppService.h index 2c617af8d708..4e9ddaf4f0bc 100644 --- a/uriloader/exthandler/android/nsOSHelperAppService.h +++ b/uriloader/exthandler/android/nsOSHelperAppService.h @@ -14,15 +14,16 @@ class nsOSHelperAppService : public nsExternalHelperAppService { nsOSHelperAppService(); virtual ~nsOSHelperAppService(); - virtual already_AddRefed GetMIMEInfoFromOS( - const nsACString& aMIMEType, const nsACString& aFileExt, bool* aFound); + nsresult GetMIMEInfoFromOS(const nsACString& aMIMEType, + const nsACString& aFileExt, bool* aFound, + nsIMIMEInfo** aMIMEInfo) override; - virtual MOZ_MUST_USE nsresult OSProtocolHandlerExists(const char* aScheme, - bool* aExists); + MOZ_MUST_USE nsresult OSProtocolHandlerExists(const char* aScheme, + bool* aExists) override; NS_IMETHOD GetProtocolHandlerInfoFromOS(const nsACString& aScheme, bool* found, - nsIHandlerInfo** _retval); + nsIHandlerInfo** _retval) override; static nsIHandlerApp* CreateAndroidHandlerApp( const nsAString& aName, const nsAString& aDescription, diff --git a/uriloader/exthandler/mac/nsOSHelperAppService.h b/uriloader/exthandler/mac/nsOSHelperAppService.h index c68db4b206d0..9234a3f1cb00 100644 --- a/uriloader/exthandler/mac/nsOSHelperAppService.h +++ b/uriloader/exthandler/mac/nsOSHelperAppService.h @@ -26,29 +26,22 @@ class nsOSHelperAppService : public nsExternalHelperAppService { NS_IMETHOD GetApplicationDescription(const nsACString& aScheme, nsAString& _retval) override; - // method overrides --> used to hook the mime service into internet config.... - NS_IMETHOD GetFromTypeAndExtension(const nsACString& aType, - const nsACString& aFileExt, - nsIMIMEInfo** aMIMEInfo) override; - already_AddRefed GetMIMEInfoFromOS(const nsACString& aMIMEType, - const nsACString& aFileExt, - bool* aFound) override; + nsresult GetMIMEInfoFromOS(const nsACString& aMIMEType, + const nsACString& aFileExt, bool* aFound, + nsIMIMEInfo** aMIMEInfo) override; + NS_IMETHOD GetProtocolHandlerInfoFromOS(const nsACString& aScheme, bool* found, nsIHandlerInfo** _retval) override; - // override so we can have a child process sandbox-friendly implementation - bool GetMIMETypeFromOSForExtension(const nsACString& aExtension, - nsACString& aMIMEType) override; - // 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 // aFile --> an nsIFile representation of that platform application path. - virtual MOZ_MUST_USE nsresult GetFileTokenForPath( - const char16_t* platformAppPath, nsIFile** aFile) override; + MOZ_MUST_USE nsresult GetFileTokenForPath(const char16_t* platformAppPath, + nsIFile** aFile) override; MOZ_MUST_USE nsresult OSProtocolHandlerExists(const char* aScheme, bool* aHandlerExists) override; diff --git a/uriloader/exthandler/mac/nsOSHelperAppService.mm b/uriloader/exthandler/mac/nsOSHelperAppService.mm index 78c5f34f1522..0a00725a9da9 100644 --- a/uriloader/exthandler/mac/nsOSHelperAppService.mm +++ b/uriloader/exthandler/mac/nsOSHelperAppService.mm @@ -58,8 +58,8 @@ nsOSHelperAppService::~nsOSHelperAppService() {} nsresult nsOSHelperAppService::OSProtocolHandlerExists(const char *aProtocolScheme, bool *aHandlerExists) { // CFStringCreateWithBytes() can fail even if we're not out of memory -- - // for example if the 'bytes' parameter is something very wierd (like "ÿÿ~" - // aka "\xFF\xFF~"), or possibly if it can't be interpreted as using what's + // for example if the 'bytes' parameter is something very weird (like + // "\xFF\xFF~"), or possibly if it can't be interpreted as using what's // specified in the 'encoding' parameter. See bug 548719. CFStringRef schemeString = ::CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)aProtocolScheme, @@ -197,12 +197,6 @@ nsresult nsOSHelperAppService::GetFileTokenForPath(const char16_t *aPlatformAppP NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } -NS_IMETHODIMP nsOSHelperAppService::GetFromTypeAndExtension(const nsACString &aType, - const nsACString &aFileExt, - nsIMIMEInfo **aMIMEInfo) { - return nsExternalHelperAppService::GetFromTypeAndExtension(aType, aFileExt, aMIMEInfo); -} - // Returns the MIME types an application bundle explicitly claims to handle. // Returns NULL if aAppRef doesn't explicitly claim to handle any MIME types. // If the return value is non-NULL, the caller is responsible for freeing it. @@ -275,12 +269,11 @@ static CFArrayRef GetMIMETypesHandledByApp(FSRef *aAppRef) { return mimeTypes; } -// aMIMEType and aFileExt might not match, If they don't we set *aFound to -// false and return a minimal nsIMIMEInfo structure. -already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString &aMIMEType, - const nsACString &aFileExt, - bool *aFound) { +nsresult nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString &aMIMEType, + const nsACString &aFileExt, bool *aFound, + nsIMIMEInfo **aMIMEInfo) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSNULL; + MOZ_ASSERT(XRE_IsParentProcess()); *aFound = false; @@ -310,8 +303,8 @@ already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS(const nsAC typeIsOctetStream = aMIMEType.LowerCaseEqualsLiteral(APPLICATION_OCTET_STREAM); CFURLRef appURL = NULL; // CFStringCreateWithCString() can fail even if we're not out of memory -- - // for example if the 'cStr' parameter is something very weird (like "ÿÿ~" - // aka "\xFF\xFF~"), or possibly if it can't be interpreted as using what's + // for example if the 'cStr' parameter is something very weird (like + // "\xFF\xFF~"), or possibly if it can't be interpreted as using what's // specified in the 'encoding' parameter. See bug 548719. cfMIMEType = ::CFStringCreateWithCString(NULL, flatType.get(), kCFStringEncodingUTF8); if (cfMIMEType) { @@ -328,8 +321,8 @@ already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS(const nsAC } if (!aFileExt.IsEmpty()) { // CFStringCreateWithCString() can fail even if we're not out of memory -- - // for example if the 'cStr' parameter is something very wierd (like "ÿÿ~" - // aka "\xFF\xFF~"), or possibly if it can't be interpreted as using what's + // for example if the 'cStr' parameter is something very weird (like + // "\xFF\xFF~"), or possibly if it can't be interpreted as using what's // specified in the 'encoding' parameter. See bug 548719. CFStringRef cfExt = ::CFStringCreateWithCString(NULL, flatExt.get(), kCFStringEncodingUTF8); if (cfExt) { @@ -445,10 +438,11 @@ already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS(const nsAC if (typeAppIsDefault || extAppIsDefault) { if (haveAppForExt) mimeInfoMac->AppendExtension(aFileExt); - nsCOMPtr app(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID)); - if (!app) { + nsresult rv; + nsCOMPtr app(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv)); + if (NS_FAILED(rv)) { [localPool release]; - return nullptr; + return rv; } CFStringRef cfAppName = NULL; @@ -516,9 +510,10 @@ already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS(const nsAC MOZ_LOG(mLog, LogLevel::Debug, ("OS gave us: type '%s' found '%i'\n", mimeType.get(), *aFound)); [localPool release]; - return mimeInfoMac.forget(); + mimeInfoMac.forget(aMIMEInfo); + return NS_OK; - NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL; + NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } NS_IMETHODIMP @@ -550,31 +545,3 @@ nsOSHelperAppService::GetProtocolHandlerInfoFromOS(const nsACString &aScheme, bo return NS_OK; } - -/* - * Override GetMIMETypeFromOSForExtension() so that we can proxy requests for - * the MIME type to the parent when we're executing in the child process. If - * we're in the parent process, query the OS directly. - */ -bool nsOSHelperAppService::GetMIMETypeFromOSForExtension(const nsACString &aExtension, - nsACString &aMIMEType) { - if (XRE_IsParentProcess()) { - return nsExternalHelperAppService::GetMIMETypeFromOSForExtension(aExtension, aMIMEType); - } - - nsCOMPtr handlerSvc = do_GetService(NS_HANDLERSERVICE_CONTRACTID); - if (NS_WARN_IF(!handlerSvc)) { - return false; - } - - nsresult rv = handlerSvc->GetTypeFromExtension(aExtension, aMIMEType); - if (NS_WARN_IF(NS_FAILED(rv))) { - return false; - } - - if (aMIMEType.IsEmpty()) { - return false; - } - - return true; -} diff --git a/uriloader/exthandler/moz.build b/uriloader/exthandler/moz.build index d8fd3aa236f5..ec0ef6ce045d 100644 --- a/uriloader/exthandler/moz.build +++ b/uriloader/exthandler/moz.build @@ -36,6 +36,8 @@ EXPORTS += [ EXPORTS += [ 'ContentHandlerService.h', 'nsExternalHelperAppService.h', + 'nsMIMEInfoChild.h', + 'nsOSHelperAppServiceChild.h', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': @@ -61,6 +63,7 @@ UNIFIED_SOURCES += [ 'nsExternalProtocolHandler.cpp', 'nsLocalHandlerApp.cpp', 'nsMIMEInfoImpl.cpp', + 'nsOSHelperAppServiceChild.cpp', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp index 6ee76a9d3e33..250b413f3bcf 100644 --- a/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -43,6 +43,8 @@ #include "nsAutoPtr.h" #include "nsIMutableArray.h" #include "nsIRedirectHistoryEntry.h" +#include "nsOSHelperAppService.h" +#include "nsOSHelperAppServiceChild.h" // used to access our datastore of user-configured helper applications #include "nsIHandlerService.h" @@ -105,6 +107,7 @@ # include "FennecJNIWrappers.h" #endif +#include "mozilla/ClearOnShutdown.h" #include "mozilla/Preferences.h" #include "mozilla/ipc/URIUtils.h" @@ -573,6 +576,32 @@ static const nsDefaultMimeTypeEntry nonDecodableExtensions[] = { {APPLICATION_COMPRESS, "z"}, {APPLICATION_GZIP, "svgz"}}; +static StaticRefPtr sExtHelperAppSvcSingleton; + +/** + * On Mac child processes, return an nsOSHelperAppServiceChild for remoting + * OS calls to the parent process. On all other platforms use + * nsOSHelperAppService. + */ +/* static */ +already_AddRefed +nsExternalHelperAppService::GetSingleton() { + if (!sExtHelperAppSvcSingleton) { +#ifdef XP_MACOSX + if (XRE_IsParentProcess()) { + sExtHelperAppSvcSingleton = new nsOSHelperAppService(); + } else { + sExtHelperAppSvcSingleton = new nsOSHelperAppServiceChild(); + } +#else + sExtHelperAppSvcSingleton = new nsOSHelperAppService(); +#endif /* XP_MACOSX */ + ClearOnShutdown(&sExtHelperAppSvcSingleton); + } + + return do_AddRef(sExtHelperAppSvcSingleton); +} + NS_IMPL_ISUPPORTS(nsExternalHelperAppService, nsIExternalHelperAppService, nsPIExternalAppLauncher, nsIExternalProtocolService, nsIMIMEService, nsIObserver, nsISupportsWeakReference) @@ -2483,7 +2512,11 @@ NS_IMETHODIMP nsExternalHelperAppService::GetFromTypeAndExtension( // (1) Ask the OS for a mime info bool found; - *_retval = GetMIMEInfoFromOS(typeToUse, aFileExt, &found).take(); + nsresult rv = GetMIMEInfoFromOS(typeToUse, aFileExt, &found, _retval); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + LOG(("OS gave back 0x%p - found: %i\n", *_retval, found)); // If we got no mimeinfo, something went wrong. Probably lack of memory. if (!*_retval) return NS_ERROR_OUT_OF_MEMORY; @@ -2491,7 +2524,6 @@ NS_IMETHODIMP nsExternalHelperAppService::GetFromTypeAndExtension( // (2) Now, let's see if we can find something in our datastore // This will not overwrite the OS information that interests us // (i.e. default application, default app. description) - nsresult rv; nsCOMPtr handlerSvc = do_GetService(NS_HANDLERSERVICE_CONTRACTID); if (handlerSvc) { @@ -2796,7 +2828,17 @@ bool nsExternalHelperAppService::GetTypeFromExtras(const nsACString& aExtension, bool nsExternalHelperAppService::GetMIMETypeFromOSForExtension( const nsACString& aExtension, nsACString& aMIMEType) { bool found = false; - nsCOMPtr mimeInfo = - GetMIMEInfoFromOS(EmptyCString(), aExtension, &found); - return found && mimeInfo && NS_SUCCEEDED(mimeInfo->GetMIMEType(aMIMEType)); + nsCOMPtr mimeInfo; + nsresult rv = GetMIMEInfoFromOS(EmptyCString(), aExtension, &found, + getter_AddRefs(mimeInfo)); + return NS_SUCCEEDED(rv) && found && mimeInfo && + NS_SUCCEEDED(mimeInfo->GetMIMEType(aMIMEType)); +} + +nsresult nsExternalHelperAppService::GetMIMEInfoFromOS( + const nsACString& aMIMEType, const nsACString& aFileExt, bool* aFound, + nsIMIMEInfo** aMIMEInfo) { + *aMIMEInfo = nullptr; + *aFound = false; + return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/uriloader/exthandler/nsExternalHelperAppService.h b/uriloader/exthandler/nsExternalHelperAppService.h index 155a32d06f09..99e2694d48e6 100644 --- a/uriloader/exthandler/nsExternalHelperAppService.h +++ b/uriloader/exthandler/nsExternalHelperAppService.h @@ -67,25 +67,6 @@ class nsExternalHelperAppService : public nsIExternalHelperAppService, */ MOZ_MUST_USE nsresult Init(); - /** - * 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. - * This is supposed to be overridden by the platform-specific - * nsOSHelperAppService! - * @param aFileExt The file extension; may be empty. UTF-8 encoded. - * @param [out] aFound - * Should be set to true if the os has a mapping, to - * false otherwise. Must not be null. - * @return A MIMEInfo. This function must return a MIMEInfo object if it - * can allocate one. The only justifiable reason for not - * returning one is an out-of-memory error. - * If null, the value of aFound is unspecified. - */ - virtual already_AddRefed GetMIMEInfoFromOS( - const nsACString& aMIMEType, const nsACString& aFileExt, - bool* aFound) = 0; - /** * Given a string identifying an application, create an nsIFile representing * it. This function should look in $PATH for the application. @@ -103,8 +84,7 @@ class nsExternalHelperAppService : public nsIExternalHelperAppService, virtual nsresult GetFileTokenForPath(const char16_t* platformAppPath, nsIFile** aFile); - virtual nsresult OSProtocolHandlerExists(const char* aScheme, - bool* aExists) = 0; + NS_IMETHOD OSProtocolHandlerExists(const char* aScheme, bool* aExists) = 0; /** * Given an extension, get a MIME type string. If not overridden by @@ -115,6 +95,8 @@ class nsExternalHelperAppService : public nsIExternalHelperAppService, virtual bool GetMIMETypeFromOSForExtension(const nsACString& aExtension, nsACString& aMIMEType); + static already_AddRefed GetSingleton(); + protected: virtual ~nsExternalHelperAppService(); diff --git a/uriloader/exthandler/nsIHandlerService.idl b/uriloader/exthandler/nsIHandlerService.idl index 83c9f67b466b..34519f57cd95 100644 --- a/uriloader/exthandler/nsIHandlerService.idl +++ b/uriloader/exthandler/nsIHandlerService.idl @@ -129,5 +129,34 @@ interface nsIHandlerService : nsISupports * * @returns whether or not a handler exists */ + boolean existsForProtocolOS(in ACString aProtocolScheme); + + /** + * Whether or not there is a handler in the datastore or OS for + * the specified protocol type. If there is no handler in the datastore, + * falls back to a check for an OS handler. + * + * @param aProtocolScheme scheme to check for support + * + * @returns whether or not a handler exists + */ boolean existsForProtocol(in ACString aProtocolScheme); + + /* + * Fill in a handler info object using information from the OS, taking into + * account the MIME type and file extension. When the OS handler + * for the MIME type and extension match, |aFound| is returned as true. If + * either the MIME type or extension is the empty string and a handler is + * found, |aFound| is returned as true. + */ + void getMIMEInfoFromOS(in nsIHandlerInfo aHandlerInfo, + in ACString aMIMEType, + in ACString aExtension, + out bool aFound); + + /* + * Get a description for the application responsible for handling + * the provided protocol. + */ + AString getApplicationDescription(in ACString aProtocolScheme); }; diff --git a/uriloader/exthandler/nsMIMEInfoChild.h b/uriloader/exthandler/nsMIMEInfoChild.h new file mode 100644 index 000000000000..bf4ad70a1c42 --- /dev/null +++ b/uriloader/exthandler/nsMIMEInfoChild.h @@ -0,0 +1,49 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsMIMEInfoChild_h +#define nsMIMEInfoChild_h + +#include "nsMIMEInfoImpl.h" + +/* + * A platform-generic nsMIMEInfo implementation to be used in child process + * generic code that needs a MIMEInfo with limited functionality. + */ +class nsChildProcessMIMEInfo : public nsMIMEInfoImpl { + public: + explicit nsChildProcessMIMEInfo(const char* aMIMEType = "") + : nsMIMEInfoImpl(aMIMEType) {} + + explicit nsChildProcessMIMEInfo(const nsACString& aMIMEType) + : nsMIMEInfoImpl(aMIMEType) {} + + nsChildProcessMIMEInfo(const nsACString& aType, HandlerClass aClass) + : nsMIMEInfoImpl(aType, aClass) {} + + NS_IMETHOD LaunchWithFile(nsIFile* aFile) override { + return NS_ERROR_NOT_IMPLEMENTED; + }; + + protected: + virtual MOZ_MUST_USE nsresult LoadUriInternal(nsIURI* aURI) override { + return NS_ERROR_NOT_IMPLEMENTED; + }; + +#ifdef DEBUG + virtual MOZ_MUST_USE nsresult LaunchDefaultWithFile(nsIFile* aFile) override { + return NS_ERROR_UNEXPECTED; + } +#endif + static MOZ_MUST_USE nsresult OpenApplicationWithURI(nsIFile* aApplication, + const nsCString& aURI) { + return NS_ERROR_NOT_IMPLEMENTED; + } + + NS_IMETHOD GetDefaultDescription(nsAString& aDefaultDescription) override { + return NS_ERROR_NOT_IMPLEMENTED; + }; +}; + +#endif diff --git a/uriloader/exthandler/nsOSHelperAppServiceChild.cpp b/uriloader/exthandler/nsOSHelperAppServiceChild.cpp new file mode 100644 index 000000000000..4dc302662153 --- /dev/null +++ b/uriloader/exthandler/nsOSHelperAppServiceChild.cpp @@ -0,0 +1,149 @@ +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include +#include +#include "mozilla/Logging.h" +#include "mozilla/net/NeckoCommon.h" +#include "nsOSHelperAppServiceChild.h" +#include "nsMIMEInfoChild.h" +#include "nsISupports.h" +#include "nsString.h" +#include "nsTArray.h" +#include "nsIURL.h" +#include "nsIFile.h" +#include "nsIHandlerService.h" +#include "nsMimeTypes.h" +#include "nsMIMEInfoImpl.h" +#include "nsIStringBundle.h" +#include "nsIPromptService.h" +#include "nsMemory.h" +#include "nsCRT.h" +#include "nsEmbedCID.h" + +#undef LOG +#define LOG(args) \ + MOZ_LOG(nsExternalHelperAppService::mLog, mozilla::LogLevel::Info, args) +#undef LOG_ERR +#define LOG_ERR(args) \ + MOZ_LOG(nsExternalHelperAppService::mLog, mozilla::LogLevel::Error, args) +#undef LOG_ENABLED +#define LOG_ENABLED() \ + MOZ_LOG_TEST(nsExternalHelperAppService::mLog, mozilla::LogLevel::Info) + +nsresult nsOSHelperAppServiceChild::ExternalProtocolHandlerExists( + const char* aProtocolScheme, bool* aHandlerExists) { + nsresult rv; + nsCOMPtr handlerSvc = + do_GetService(NS_HANDLERSERVICE_CONTRACTID, &rv); + if (NS_WARN_IF(NS_FAILED(rv))) { + LOG_ERR(("nsOSHelperAppServiceChild error: no handler service")); + return rv; + } + + nsAutoCString scheme(aProtocolScheme); + *aHandlerExists = false; + rv = handlerSvc->ExistsForProtocol(scheme, aHandlerExists); + LOG( + ("nsOSHelperAppServiceChild::OSProtocolHandlerExists(): " + "protocol: %s, result: %" PRId32, + aProtocolScheme, static_cast(rv))); + mozilla::Unused << NS_WARN_IF(NS_FAILED(rv)); + return rv; +} + +nsresult nsOSHelperAppServiceChild::OSProtocolHandlerExists(const char* aScheme, + bool* aExists) { + // Use ExternalProtocolHandlerExists() which includes the + // OS-level check and remotes the call to the parent process. + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsOSHelperAppServiceChild::GetApplicationDescription(const nsACString& aScheme, + nsAString& aRetVal) { + nsresult rv; + nsCOMPtr handlerSvc = + do_GetService(NS_HANDLERSERVICE_CONTRACTID, &rv); + if (NS_WARN_IF(NS_FAILED(rv))) { + LOG_ERR(("nsOSHelperAppServiceChild error: no handler service")); + return rv; + } + + rv = handlerSvc->GetApplicationDescription(aScheme, aRetVal); + LOG( + ("nsOSHelperAppServiceChild::GetApplicationDescription(): " + "scheme: %s, result: %" PRId32 ", description: %s", + PromiseFlatCString(aScheme).get(), static_cast(rv), + NS_ConvertUTF16toUTF8(aRetVal).get())); + mozilla::Unused << NS_WARN_IF(NS_FAILED(rv)); + return rv; +} + +NS_IMETHODIMP +nsOSHelperAppServiceChild::GetMIMEInfoFromOS(const nsACString& aMIMEType, + const nsACString& aFileExt, + bool* aFound, + nsIMIMEInfo** aMIMEInfo) { + RefPtr mimeInfo = + new nsChildProcessMIMEInfo(aMIMEType); + + nsCOMPtr handlerSvc = + do_GetService(NS_HANDLERSERVICE_CONTRACTID); + if (handlerSvc) { + nsresult rv = + handlerSvc->GetMIMEInfoFromOS(mimeInfo, aMIMEType, aFileExt, aFound); + LOG( + ("nsOSHelperAppServiceChild::GetMIMEInfoFromOS(): " + "MIME type: %s, extension: %s, result: %" PRId32, + PromiseFlatCString(aMIMEType).get(), + PromiseFlatCString(aFileExt).get(), static_cast(rv))); + mozilla::Unused << NS_WARN_IF(NS_FAILED(rv)); + if (NS_FAILED(rv)) { + return rv; + } + } else { + LOG_ERR(("nsOSHelperAppServiceChild error: no handler service")); + *aFound = false; + } + + mimeInfo.forget(aMIMEInfo); + return NS_OK; +} + +NS_IMETHODIMP +nsOSHelperAppServiceChild::GetProtocolHandlerInfoFromOS( + const nsACString& aScheme, bool* aFound, nsIHandlerInfo** aRetVal) { + MOZ_ASSERT(!aScheme.IsEmpty(), "No scheme was specified!"); + + nsresult rv = + OSProtocolHandlerExists(PromiseFlatCString(aScheme).get(), aFound); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + nsChildProcessMIMEInfo* handlerInfo = + new nsChildProcessMIMEInfo(aScheme, nsMIMEInfoBase::eProtocolInfo); + NS_ENSURE_TRUE(handlerInfo, NS_ERROR_OUT_OF_MEMORY); + NS_ADDREF(*aRetVal = handlerInfo); + + if (!*aFound) { + // Code that calls this requires an object no matter whether the OS has + // something for us, so we return the empty object. + return NS_OK; + } + + nsAutoString description; + rv = GetApplicationDescription(aScheme, description); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "GetApplicationDescription failed"); + handlerInfo->SetDefaultDescription(description); + return NS_OK; +} + +nsresult nsOSHelperAppServiceChild::GetFileTokenForPath( + const char16_t* platformAppPath, nsIFile** aFile) { + return NS_ERROR_NOT_IMPLEMENTED; +} diff --git a/uriloader/exthandler/nsOSHelperAppServiceChild.h b/uriloader/exthandler/nsOSHelperAppServiceChild.h new file mode 100644 index 000000000000..bf1535f8c37d --- /dev/null +++ b/uriloader/exthandler/nsOSHelperAppServiceChild.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsOSHelperAppServiceChild_h__ +#define nsOSHelperAppServiceChild_h__ + +#include "nsExternalHelperAppService.h" + +class nsIMIMEInfo; + +/* + * Provides a generic implementation of the nsExternalHelperAppService + * platform-specific methods by remoting calls to the parent process. + * Only provides implementations for the methods needed in unprivileged + * child processes. + */ +class nsOSHelperAppServiceChild : public nsExternalHelperAppService { + public: + nsOSHelperAppServiceChild() : nsExternalHelperAppService(){}; + virtual ~nsOSHelperAppServiceChild() = default; + + NS_IMETHOD GetProtocolHandlerInfoFromOS(const nsACString& aScheme, + bool* found, + nsIHandlerInfo** _retval) override; + + nsresult GetFileTokenForPath(const char16_t* platformAppPath, + nsIFile** aFile) override; + + NS_IMETHOD ExternalProtocolHandlerExists(const char* aProtocolScheme, + bool* aHandlerExists) override; + + NS_IMETHOD OSProtocolHandlerExists(const char* aScheme, + bool* aExists) override; + + NS_IMETHOD GetApplicationDescription(const nsACString& aScheme, + nsAString& aRetVal) override; + + NS_IMETHOD GetMIMEInfoFromOS(const nsACString& aMIMEType, + const nsACString& aFileExt, bool* aFound, + nsIMIMEInfo** aMIMEInfo) override; +}; + +#endif // nsOSHelperAppServiceChild_h__ diff --git a/uriloader/exthandler/uikit/nsOSHelperAppService.h b/uriloader/exthandler/uikit/nsOSHelperAppService.h index 6f56fb5c28a0..78bea7da7404 100644 --- a/uriloader/exthandler/uikit/nsOSHelperAppService.h +++ b/uriloader/exthandler/uikit/nsOSHelperAppService.h @@ -29,9 +29,9 @@ class nsOSHelperAppService final : public nsExternalHelperAppService { NS_IMETHOD GetFromTypeAndExtension(const nsACString& aType, const nsACString& aFileExt, nsIMIMEInfo** aMIMEInfo); - already_AddRefed GetMIMEInfoFromOS(const nsACString& aMIMEType, - const nsACString& aFileExt, - bool* aFound); + NS_IMETHOD GetMIMEInfoFromOS(const nsACString& aMIMEType, + const nsACString& aFileExt, bool* aFound, + nsIMIMEInfo** aMIMEInfo) override; NS_IMETHOD GetProtocolHandlerInfoFromOS(const nsACString& aScheme, bool* found, nsIHandlerInfo** _retval); @@ -45,7 +45,8 @@ class nsOSHelperAppService final : public nsExternalHelperAppService { virtual nsresult GetFileTokenForPath(const char16_t* platformAppPath, nsIFile** aFile); - nsresult OSProtocolHandlerExists(const char* aScheme, bool* aHandlerExists); + nsresult OSProtocolHandlerExists(const char* aScheme, + bool* aHandlerExists) override; }; #endif // nsOSHelperAppService_h__ diff --git a/uriloader/exthandler/uikit/nsOSHelperAppService.mm b/uriloader/exthandler/uikit/nsOSHelperAppService.mm index 6b459eb37339..f4336907f406 100644 --- a/uriloader/exthandler/uikit/nsOSHelperAppService.mm +++ b/uriloader/exthandler/uikit/nsOSHelperAppService.mm @@ -32,15 +32,16 @@ nsOSHelperAppService::GetFromTypeAndExtension(const nsACString& aType, const nsA return nsExternalHelperAppService::GetFromTypeAndExtension(aType, aFileExt, aMIMEInfo); } -already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType, - const nsACString& aFileExt, - bool* aFound) { +NS_IMETHODIMP nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType, + const nsACString& aFileExt, bool* aFound, + nsIMIMEInfo** aMIMEInfo) { + *aMIMEInfo = nullptr; *aFound = false; - return nullptr; + return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsOSHelperAppService::GetProtocolHandlerInfoFromOS(const nsACString& aScheme, bool* found, +nsOSHelperAppService::GetProtocolHandlerInfoFromOS(const char* aScheme, bool* found, nsIHandlerInfo** _retval) { *found = false; return NS_OK; diff --git a/uriloader/exthandler/unix/nsOSHelperAppService.cpp b/uriloader/exthandler/unix/nsOSHelperAppService.cpp index 054029dcc7e1..7e66e1e57dd3 100644 --- a/uriloader/exthandler/unix/nsOSHelperAppService.cpp +++ b/uriloader/exthandler/unix/nsOSHelperAppService.cpp @@ -1039,8 +1039,8 @@ nsresult nsOSHelperAppService::OSProtocolHandlerExists( nsCOMPtr handlerSvc = do_GetService(NS_HANDLERSERVICE_CONTRACTID, &rv); if (NS_SUCCEEDED(rv) && handlerSvc) { - rv = handlerSvc->ExistsForProtocol(nsCString(aProtocolScheme), - aHandlerExists); + rv = handlerSvc->ExistsForProtocolOS(nsCString(aProtocolScheme), + aHandlerExists); } } @@ -1324,8 +1324,10 @@ already_AddRefed nsOSHelperAppService::GetFromType( return mimeInfo.forget(); } -already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS( - const nsACString& aType, const nsACString& aFileExt, bool* aFound) { +nsresult nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aType, + const nsACString& aFileExt, + bool* aFound, + nsIMIMEInfo** aMIMEInfo) { *aFound = true; RefPtr retval; // Fallback to lookup by extension when generic 'application/octet-stream' @@ -1339,14 +1341,18 @@ already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS( RefPtr miByExt = GetFromExtension(PromiseFlatCString(aFileExt)); // If we had no extension match, but a type match, use that - if (!miByExt && retval) return retval.forget(); + if (!miByExt && retval) { + retval.forget(aMIMEInfo); + return NS_OK; + } // If we had an extension match but no type match, set the mimetype and use // it if (!retval && miByExt) { if (!aType.IsEmpty()) miByExt->SetMIMEType(aType); miByExt.swap(retval); - return retval.forget(); + retval.forget(aMIMEInfo); + return NS_OK; } // If we got nothing, make a new mimeinfo if (!retval) { @@ -1356,7 +1362,8 @@ already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS( if (!aFileExt.IsEmpty()) retval->AppendExtension(aFileExt); } - return retval.forget(); + retval.forget(aMIMEInfo); + return NS_OK; } // Copy the attributes of retval (mimeinfo from type) onto miByExt, to @@ -1369,7 +1376,8 @@ already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS( miByExt.swap(retval); } - return retval.forget(); + retval.forget(aMIMEInfo); + return NS_OK; } NS_IMETHODIMP diff --git a/uriloader/exthandler/unix/nsOSHelperAppService.h b/uriloader/exthandler/unix/nsOSHelperAppService.h index 45866b859f71..7b412f701bd2 100644 --- a/uriloader/exthandler/unix/nsOSHelperAppService.h +++ b/uriloader/exthandler/unix/nsOSHelperAppService.h @@ -24,9 +24,9 @@ class nsOSHelperAppService : public nsExternalHelperAppService { virtual ~nsOSHelperAppService(); // method overrides for mime.types and mime.info look up steps - already_AddRefed GetMIMEInfoFromOS(const nsACString& aMimeType, - const nsACString& aFileExt, - bool* aFound) override; + NS_IMETHOD GetMIMEInfoFromOS(const nsACString& aMimeType, + const nsACString& aFileExt, bool* aFound, + nsIMIMEInfo** aMIMEInfo) override; NS_IMETHOD GetProtocolHandlerInfoFromOS(const nsACString& aScheme, bool* found, nsIHandlerInfo** _retval) override; diff --git a/uriloader/exthandler/win/nsOSHelperAppService.cpp b/uriloader/exthandler/win/nsOSHelperAppService.cpp index b6e596c95187..4d0863bb997b 100644 --- a/uriloader/exthandler/win/nsOSHelperAppService.cpp +++ b/uriloader/exthandler/win/nsOSHelperAppService.cpp @@ -376,8 +376,10 @@ already_AddRefed nsOSHelperAppService::GetByExtension( return mimeInfo.forget(); } -already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS( - const nsACString& aMIMEType, const nsACString& aFileExt, bool* aFound) { +NS_IMETHODIMP +nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType, + const nsACString& aFileExt, + bool* aFound, nsIMIMEInfo** aMIMEInfo) { *aFound = true; const nsCString& flatType = PromiseFlatCString(aMIMEType); @@ -430,9 +432,13 @@ already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS( RefPtr miByExt = GetByExtension(NS_ConvertUTF8toUTF16(aFileExt), flatType.get()); LOG(("Ext. lookup for '%s' found 0x%p\n", flatExt.get(), miByExt.get())); - if (!miByExt && mi) return mi.forget(); + if (!miByExt && mi) { + mi.forget(aMIMEInfo); + return NS_OK; + } if (miByExt && !mi) { - return miByExt.forget(); + miByExt.forget(aMIMEInfo); + return NS_OK; } if (!miByExt && !mi) { *aFound = false; @@ -441,7 +447,8 @@ already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS( mi->AppendExtension(aFileExt); } - return mi.forget(); + mi.forget(aMIMEInfo); + return NS_OK; } // if we get here, mi has no default app. copy from extension lookup. @@ -451,7 +458,8 @@ already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS( mi->SetDefaultDescription(desc); } - return mi.forget(); + mi.forget(aMIMEInfo); + return NS_OK; } NS_IMETHODIMP diff --git a/uriloader/exthandler/win/nsOSHelperAppService.h b/uriloader/exthandler/win/nsOSHelperAppService.h index 728a831759ff..350fbea21f3a 100644 --- a/uriloader/exthandler/win/nsOSHelperAppService.h +++ b/uriloader/exthandler/win/nsOSHelperAppService.h @@ -31,16 +31,16 @@ class nsOSHelperAppService : public nsExternalHelperAppService { virtual ~nsOSHelperAppService(); // override nsIExternalProtocolService methods - nsresult OSProtocolHandlerExists(const char* aProtocolScheme, - bool* aHandlerExists); + NS_IMETHOD OSProtocolHandlerExists(const char* aProtocolScheme, + bool* aHandlerExists) override; nsresult LoadUriInternal(nsIURI* aURL); NS_IMETHOD GetApplicationDescription(const nsACString& aScheme, nsAString& _retval) override; // method overrides for windows registry look up steps.... - already_AddRefed GetMIMEInfoFromOS(const nsACString& aMIMEType, - const nsACString& aFileExt, - bool* aFound); + NS_IMETHOD GetMIMEInfoFromOS(const nsACString& aMIMEType, + const nsACString& aFileExt, bool* aFound, + nsIMIMEInfo** aMIMEInfo) override; NS_IMETHOD GetProtocolHandlerInfoFromOS(const nsACString& aScheme, bool* found, nsIHandlerInfo** _retval);