[uri] Fix issues with external protocol handlers.

Remove early return in nsExternalProtocolHandler::NewChannel when handler doesn't exist.
Fix devtools expectation that newChannel throws for unsupported external handlers
This commit is contained in:
Moonchild 2024-06-11 19:19:55 +02:00 • committed by roytam1
commit a09accc204
4 changed files with 13 additions and 43 deletions

View file

@ -537,6 +537,7 @@ function newChannelForURL(url, { policy, window, principal }) {
// scheme to see if it helps. // scheme to see if it helps.
uri = Services.io.newURI("file://" + url, null, null); uri = Services.io.newURI("file://" + url, null, null);
} }
let channelOptions = { let channelOptions = {
contentPolicyType: policy, contentPolicyType: policy,
securityFlags: securityFlags, securityFlags: securityFlags,
@ -557,15 +558,7 @@ function newChannelForURL(url, { policy, window, principal }) {
} }
channelOptions.loadingPrincipal = prin; channelOptions.loadingPrincipal = prin;
try { return NetUtil.newChannel(channelOptions);
return NetUtil.newChannel(channelOptions);
} catch (e) {
// In xpcshell tests on Windows, nsExternalProtocolHandler::NewChannel()
// can throw NS_ERROR_UNKNOWN_PROTOCOL if the external protocol isn't
// supported by Windows, so we also need to handle the exception here if
// parsing the URL above doesn't throw.
return newChannelForURL("file://" + url, { policy, window, principal });
}
} }
// Fetch is defined differently depending on whether we are on the main thread // Fetch is defined differently depending on whether we are on the main thread

View file

@ -3,6 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ScopeExit.h"
#include "nsIURI.h" #include "nsIURI.h"
#include "nsIURL.h" #include "nsIURL.h"
#include "nsExternalProtocolHandler.h" #include "nsExternalProtocolHandler.h"
@ -155,21 +156,25 @@ nsresult nsExtProtocolChannel::OpenURL()
nsresult rv = NS_ERROR_FAILURE; nsresult rv = NS_ERROR_FAILURE;
nsCOMPtr<nsIExternalProtocolService> extProtService (do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID)); nsCOMPtr<nsIExternalProtocolService> extProtService (do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
auto cleanup = mozilla::MakeScopeExit([&] {
mCallbacks = nullptr;
});
if (extProtService) if (extProtService)
{ {
#ifdef DEBUG
nsAutoCString urlScheme; nsAutoCString urlScheme;
mUrl->GetScheme(urlScheme); mUrl->GetScheme(urlScheme);
bool haveHandler = false; bool haveHandler = false;
extProtService->ExternalProtocolHandlerExists(urlScheme.get(), &haveHandler); extProtService->ExternalProtocolHandlerExists(urlScheme.get(), &haveHandler);
NS_ASSERTION(haveHandler, "Why do we have a channel for this url if we don't support the protocol?"); if (!haveHandler) {
#endif return NS_ERROR_UNKNOWN_PROTOCOL;
}
nsCOMPtr<nsIInterfaceRequestor> aggCallbacks; nsCOMPtr<nsIInterfaceRequestor> aggCallbacks;
rv = NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup, rv = NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
getter_AddRefs(aggCallbacks)); getter_AddRefs(aggCallbacks));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
goto finish; return rv;
} }
rv = extProtService->LoadURI(mUrl, aggCallbacks); rv = extProtService->LoadURI(mUrl, aggCallbacks);
@ -181,8 +186,6 @@ nsresult nsExtProtocolChannel::OpenURL()
} }
} }
finish:
mCallbacks = nullptr;
return rv; return rv;
} }
@ -476,22 +479,6 @@ nsExternalProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_re
*_retval = false; *_retval = false;
return NS_OK; return NS_OK;
} }
// returns TRUE if the OS can handle this protocol scheme and false otherwise.
bool nsExternalProtocolHandler::HaveExternalProtocolHandler(nsIURI * aURI)
{
MOZ_ASSERT(aURI);
nsAutoCString scheme;
aURI->GetScheme(scheme);
nsCOMPtr<nsIExternalProtocolService> extProtSvc(do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
if (!extProtSvc) {
return false;
}
bool haveHandler = false;
extProtSvc->ExternalProtocolHandlerExists(scheme.get(), &haveHandler);
return haveHandler;
}
NS_IMETHODIMP nsExternalProtocolHandler::GetProtocolFlags(uint32_t *aUritype) NS_IMETHODIMP nsExternalProtocolHandler::GetProtocolFlags(uint32_t *aUritype)
{ {
@ -525,14 +512,6 @@ nsExternalProtocolHandler::NewChannel2(nsIURI* aURI,
NS_ENSURE_TRUE(aURI, NS_ERROR_UNKNOWN_PROTOCOL); NS_ENSURE_TRUE(aURI, NS_ERROR_UNKNOWN_PROTOCOL);
NS_ENSURE_TRUE(aRetval, NS_ERROR_UNKNOWN_PROTOCOL); NS_ENSURE_TRUE(aRetval, NS_ERROR_UNKNOWN_PROTOCOL);
// Only try to return a channel if we have a protocol handler for the url.
// nsOSHelperAppService::LoadUriInternal relies on this to check trustedness
// for some platforms at least. (win uses ::ShellExecute and unix uses
// gnome_url_show.)
if (!HaveExternalProtocolHandler(aURI)) {
return NS_ERROR_UNKNOWN_PROTOCOL;
}
nsCOMPtr<nsIChannel> channel = new nsExtProtocolChannel(aURI, aLoadInfo); nsCOMPtr<nsIChannel> channel = new nsExtProtocolChannel(aURI, aLoadInfo);
channel.forget(aRetval); channel.forget(aRetval);
return NS_OK; return NS_OK;

View file

@ -30,8 +30,7 @@ protected:
~nsExternalProtocolHandler(); ~nsExternalProtocolHandler();
// helper function // helper function
bool HaveExternalProtocolHandler(nsIURI * aURI); nsCString m_schemeName;
nsCString m_schemeName;
}; };
#endif // nsExternalProtocolHandler_h___ #endif // nsExternalProtocolHandler_h___

View file

@ -19,7 +19,7 @@
#ifdef _WIN32_WINNT #ifdef _WIN32_WINNT
#undef _WIN32_WINNT #undef _WIN32_WINNT
#endif #endif
#define _WIN32_WINNT 0x0600 #define _WIN32_WINNT 0x0601
#include <shlobj.h> #include <shlobj.h>
class nsMIMEInfoWin; class nsMIMEInfoWin;
@ -32,7 +32,6 @@ public:
// override nsIExternalProtocolService methods // override nsIExternalProtocolService methods
nsresult OSProtocolHandlerExists(const char * aProtocolScheme, bool * aHandlerExists); nsresult OSProtocolHandlerExists(const char * aProtocolScheme, bool * aHandlerExists);
nsresult LoadUriInternal(nsIURI * aURL);
NS_IMETHOD GetApplicationDescription(const nsACString& aScheme, nsAString& _retval); NS_IMETHOD GetApplicationDescription(const nsACString& aScheme, nsAString& _retval);
// method overrides for windows registry look up steps.... // method overrides for windows registry look up steps....