diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js index f8934ed4252a..cf71e4a74e39 100644 --- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -104,13 +104,7 @@ function getTopWin({ skipPopups, forceNonPrivate } = {}) { } function doGetProtocolFlags(aURI) { - let handler = Services.io.getProtocolHandler(aURI.scheme); - // see DoGetProtocolFlags in nsIProtocolHandler.idl - return handler instanceof Ci.nsIProtocolHandlerWithDynamicFlags - ? handler - .QueryInterface(Ci.nsIProtocolHandlerWithDynamicFlags) - .getFlagsForURI(aURI) - : handler.protocolFlags; + return Services.io.getDynamicProtocolFlags(aURI); } /** diff --git a/chrome/test/unit/test_no_remote_registration.js b/chrome/test/unit/test_no_remote_registration.js index a4b2b5357545..46303ef312ce 100644 --- a/chrome/test/unit/test_no_remote_registration.js +++ b/chrome/test/unit/test_no_remote_registration.js @@ -7,14 +7,11 @@ var manifests = [do_get_file("data/test_no_remote_registration.manifest")]; registerManifests(manifests); -function ProtocolHandler(aScheme, aFlags) { +function ProtocolHandler(aScheme) { this.scheme = aScheme; - this.protocolFlags = aFlags; - this.contractID = "@mozilla.org/network/protocol;1?name=" + aScheme; } ProtocolHandler.prototype = { - defaultPort: -1, allowPort: () => false, newChannel() { throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED); @@ -28,7 +25,6 @@ var testProtocols = [ { scheme: "moz-protocol-ui-resource", flags: Ci.nsIProtocolHandler.URI_IS_UI_RESOURCE, - CID: Components.ID("{d6dedc93-558f-44fe-90f4-3b4bba8a0b14}"), shouldRegister: false, }, // It doesn't matter if it has this flag - the only flag we accept is @@ -36,21 +32,18 @@ var testProtocols = [ { scheme: "moz-protocol-local-file", flags: Ci.nsIProtocolHandler.URI_IS_LOCAL_FILE, - CID: Components.ID("{ee30d594-0a2d-4f47-89cc-d4cde320ab69}"), shouldRegister: false, }, // This clearly is non-local { scheme: "moz-protocol-loadable-by-anyone", flags: Ci.nsIProtocolHandler.URI_LOADABLE_BY_ANYONE, - CID: Components.ID("{c3735f23-3b0c-4a33-bfa0-79436dcd40b2}"), shouldRegister: false, }, // This should always be last (unless we add more flags that are OK) { scheme: "moz-protocol-local-resource", flags: Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE, - CID: Components.ID("{b79e977c-f840-469a-b413-0125cc1b62a5}"), shouldRegister: true, }, ]; @@ -77,35 +70,17 @@ function run_test() { }, }; - let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); - - // Create factories - let factories = []; - for (let i = 0; i < testProtocols.length; i++) { - factories[i] = { - scheme: testProtocols[i].scheme, - flags: testProtocols[i].flags, - CID: testProtocols[i].CID, - contractID: - "@mozilla.org/network/protocol;1?name=" + testProtocols[i].scheme, - createInstance(aIID) { - let handler = new ProtocolHandler(this.scheme, this.flags, this.CID); - return handler.QueryInterface(aIID); - }, - }; - } - - // Register our factories - for (let i = 0; i < factories.length; i++) { - let factory = factories[i]; - registrar.registerFactory( - factory.CID, - "test-" + factory.scheme, - factory.contractID, - factory + for (let protocol of testProtocols) { + Services.io.registerProtocolHandler( + protocol.scheme, + new ProtocolHandler(protocol.scheme), + protocol.flags, + -1 ); } + let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); + // Register the XULAppInfoFactory // Make sure the class ID has not already been registered let old_factory = { CID: "", factory: null }; @@ -209,10 +184,9 @@ function run_test() { } } - // Unregister our factories so we do not leak - for (let i = 0; i < factories.length; i++) { - let factory = factories[i]; - registrar.unregisterFactory(factory.CID, factory); + // Unregister our protocol handlers so we do not leak + for (let protocol of testProtocols) { + Services.io.unregisterProtocolHandler(protocol.scheme); } // Unregister XULAppInfoFactory diff --git a/dom/base/test/chrome/test_bug682305.html b/dom/base/test/chrome/test_bug682305.html index 5d9613273fed..0f5a71c432bc 100644 --- a/dom/base/test/chrome/test_bug682305.html +++ b/dom/base/test/chrome/test_bug682305.html @@ -99,14 +99,6 @@ CustomProtocol.prototype = { get scheme() { return PROTOCOL_SCHEME; }, - get protocolFlags() { - return (Ci.nsIProtocolHandler.URI_NORELATIVE | - Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE | - Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD); - }, - get defaultPort() { - return -1; - }, allowPort: function allowPort() { return false; }, @@ -118,17 +110,17 @@ CustomProtocol.prototype = { var gFactory = { register() { - var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); - - var classID = Components.ID("{ed064287-1e76-49ba-a28d-dc74394a8334}"); - var description = PROTOCOL_SCHEME + ": protocol"; - var contractID = "@mozilla.org/network/protocol;1?name=" + PROTOCOL_SCHEME; - var factory = ComponentUtils.generateSingletonFactory(CustomProtocol); - - registrar.registerFactory(classID, description, contractID, factory); + Services.io.registerProtocolHandler( + PROTOCOL_SCHEME, + new CustomProtocol(), + Ci.nsIProtocolHandler.URI_NORELATIVE | + Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE | + Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD, + -1 + ); this.unregister = function() { - registrar.unregisterFactory(classID, factory); + Services.io.unregisterProtocolHandler(PROTOCOL_SCHEME); delete this.unregister; }; }, diff --git a/dom/file/tests/test_bloburi.js b/dom/file/tests/test_bloburi.js index ebb8f9c0a532..575b3a5ba18e 100644 --- a/dom/file/tests/test_bloburi.js +++ b/dom/file/tests/test_bloburi.js @@ -18,10 +18,7 @@ var uris = [ function run_test() { for (let i = 0; i < uris.length; i++) { let uri = ios.newURI(uris[i].uri); - let handler = ios - .getProtocolHandler(uri.scheme) - .QueryInterface(Ci.nsIProtocolHandler); - let flags = handler.protocolFlags; + let flags = ios.getDynamicProtocolFlags(uri); Assert.equal( Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE & flags, diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp index 49cf86a10549..a3a38c9776df 100644 --- a/dom/security/nsContentSecurityManager.cpp +++ b/dom/security/nsContentSecurityManager.cpp @@ -1261,19 +1261,11 @@ nsresult nsContentSecurityManager::CheckChannelHasProtocolSecurityFlag( nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); - nsAutoCString scheme; - rv = uri->GetScheme(scheme); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr ios = do_GetIOService(&rv); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr handler; - rv = ios->GetProtocolHandler(scheme.get(), getter_AddRefs(handler)); - NS_ENSURE_SUCCESS(rv, rv); - uint32_t flags; - rv = handler->DoGetProtocolFlags(uri, &flags); + rv = ios->GetDynamicProtocolFlags(uri, &flags); NS_ENSURE_SUCCESS(rv, rv); uint32_t securityFlagsSet = 0; diff --git a/netwerk/base/ProtocolHandlerInfo.cpp b/netwerk/base/ProtocolHandlerInfo.cpp new file mode 100644 index 000000000000..432ff965ce44 --- /dev/null +++ b/netwerk/base/ProtocolHandlerInfo.cpp @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "ProtocolHandlerInfo.h" +#include "StaticComponents.h" +#include "nsIProtocolHandler.h" + +namespace mozilla::net { + +uint32_t ProtocolHandlerInfo::StaticProtocolFlags() const { + uint32_t flags = mInner.match( + [&](const xpcom::StaticProtocolHandler* handler) { + return handler->mProtocolFlags; + }, + [&](const RuntimeProtocolHandler& handler) { + return handler.mProtocolFlags; + }); +#if !IS_ORIGIN_IS_FULL_SPEC_DEFINED + MOZ_RELEASE_ASSERT(!(flags & nsIProtocolHandler::ORIGIN_IS_FULL_SPEC), + "ORIGIN_IS_FULL_SPEC is unsupported but used"); +#endif + return flags; +} + +int32_t ProtocolHandlerInfo::DefaultPort() const { + return mInner.match( + [&](const xpcom::StaticProtocolHandler* handler) { + return handler->mDefaultPort; + }, + [&](const RuntimeProtocolHandler& handler) { + return handler.mDefaultPort; + }); +} + +nsresult ProtocolHandlerInfo::DynamicProtocolFlags(nsIURI* aURI, + uint32_t* aFlags) const { + MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread()); + + // If we're querying dynamic flags, we'll need to fetch the actual xpcom + // component in order to check them. + if (HasDynamicFlags()) { + nsCOMPtr handler = Handler(); + if (nsCOMPtr dynamic = + do_QueryInterface(handler)) { + nsresult rv = dynamic->GetFlagsForURI(aURI, aFlags); + NS_ENSURE_SUCCESS(rv, rv); + MOZ_DIAGNOSTIC_ASSERT( + (StaticProtocolFlags() & ~nsIProtocolHandler::DYNAMIC_URI_FLAGS) == + (*aFlags & ~nsIProtocolHandler::DYNAMIC_URI_FLAGS), + "only DYNAMIC_URI_FLAGS may be changed by a " + "nsIProtocolHandlerWithDynamicFlags implementation"); + return NS_OK; + } + } + + // Otherwise, just check against static flags. + *aFlags = StaticProtocolFlags(); + return NS_OK; +} + +bool ProtocolHandlerInfo::HasDynamicFlags() const { + return mInner.match( + [&](const xpcom::StaticProtocolHandler* handler) { + return handler->mHasDynamicFlags; + }, + [&](const RuntimeProtocolHandler&) { return false; }); +} + +already_AddRefed ProtocolHandlerInfo::Handler() const { + MOZ_ASSERT(NS_IsMainThread()); + + nsCOMPtr retval; + mInner.match( + [&](const xpcom::StaticProtocolHandler* handler) { + retval = handler->Module().GetService(); + }, + [&](const RuntimeProtocolHandler& handler) { + retval = handler.mHandler.get(); + }); + return retval.forget(); +} + +} // namespace mozilla::net diff --git a/netwerk/base/ProtocolHandlerInfo.h b/netwerk/base/ProtocolHandlerInfo.h new file mode 100644 index 000000000000..337dbddcfc8b --- /dev/null +++ b/netwerk/base/ProtocolHandlerInfo.h @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 mozilla_net_ProtocolHandlerInfo_h +#define mozilla_net_ProtocolHandlerInfo_h + +#include "mozilla/Variant.h" +#include "nsProxyRelease.h" +#include "nsIProtocolHandler.h" + +namespace mozilla { +namespace xpcom { +struct StaticProtocolHandler; +} + +namespace net { + +struct RuntimeProtocolHandler { + nsMainThreadPtrHandle mHandler; + uint32_t mProtocolFlags; + int32_t mDefaultPort; +}; + +// Information about a specific protocol handler. +class ProtocolHandlerInfo { + public: + explicit ProtocolHandlerInfo(const xpcom::StaticProtocolHandler& aStatic) + : mInner(AsVariant(&aStatic)) {} + explicit ProtocolHandlerInfo(RuntimeProtocolHandler aDynamic) + : mInner(AsVariant(std::move(aDynamic))) {} + + // Returns the statically known protocol-specific flags. + // See `nsIProtocolHandler` for valid values. + uint32_t StaticProtocolFlags() const; + + // The port that this protocol normally uses. + // If a port does not make sense for the protocol (e.g., "about:") then -1 + // will be returned. + int32_t DefaultPort() const; + + // If true, `DynamicProtocolFlags()` may return a different value than + // `StaticProtocolFlags()` for flags in `DYNAMIC_URI_FLAGS`, due to a + // `nsIProtocolHandlerWithDynamicFlags` implementation. + bool HasDynamicFlags() const; + + // Like `StaticProtocolFlags()` but also checks + // `nsIProtocolHandlerWithDynamicFlags` for uri-specific flags. + // + // NOTE: Only safe to call from the main thread. + nsresult DynamicProtocolFlags(nsIURI* aURI, uint32_t* aFlags) const + MOZ_REQUIRES(sMainThreadCapability); + + // Get the main-thread-only nsIProtocolHandler instance. + already_AddRefed Handler() const + MOZ_REQUIRES(sMainThreadCapability); + + private: + Variant mInner; +}; + +} // namespace net +} // namespace mozilla + +#endif // mozilla_net_ProtocolHandlerInfo_h diff --git a/netwerk/base/moz.build b/netwerk/base/moz.build index 693737b05168..6a157ee9730b 100644 --- a/netwerk/base/moz.build +++ b/netwerk/base/moz.build @@ -166,6 +166,7 @@ EXPORTS.mozilla.net += [ "NetworkConnectivityService.h", "Predictor.h", "PrivateBrowsingChannel.h", + "ProtocolHandlerInfo.h", "RedirectChannelRegistrar.h", "RequestContextService.h", "SimpleChannelParent.h", @@ -231,6 +232,7 @@ UNIFIED_SOURCES += [ "nsUDPSocket.cpp", "PollableEvent.cpp", "Predictor.cpp", + "ProtocolHandlerInfo.cpp", "ProxyAutoConfig.cpp", "RedirectChannelRegistrar.cpp", "RequestContextService.cpp", @@ -310,6 +312,7 @@ include("/ipc/chromium/chromium-config.mozbuild") FINAL_LIBRARY = "xul" LOCAL_INCLUDES += [ + "!/xpcom/components", "/docshell/base", "/dom/base", "/netwerk/dns", @@ -318,6 +321,7 @@ LOCAL_INCLUDES += [ "/netwerk/socket", "/netwerk/url-classifier", "/security/manager/ssl", + "/xpcom/components", ] if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa": diff --git a/netwerk/base/nsIIOService.idl b/netwerk/base/nsIIOService.idl index c11e88e5c0f5..6a4d58ceabb0 100644 --- a/netwerk/base/nsIIOService.idl +++ b/netwerk/base/nsIIOService.idl @@ -54,17 +54,30 @@ interface nsIIOService : nsISupports * Returns the protocol flags for a given scheme. * * @param aScheme the URI scheme - * @return value of corresponding nsIProtocolHandler::protocolFlags + * @return protocol flags for the corresponding protocol */ unsigned long getProtocolFlags(in string aScheme); /** - * This method constructs a new URI by determining the scheme of the - * URI spec, and then delegating the construction of the URI to the - * protocol handler for that scheme. QueryInterface can be used on - * the resulting URI object to obtain a more specific type of URI. + * Returns the dynamic protocol flags for a given URI. * - * @see nsIProtocolHandler::newURI + * @param aURI the URI to get all dynamic flags for + * @return protocol flags for that URI + */ + unsigned long getDynamicProtocolFlags(in nsIURI aURI); + + /** + * Returns the default port for a given scheme. + * + * @param aScheme the URI scheme + * @return default port for the corresponding protocol + */ + long getDefaultPort(in string aScheme); + + /** + * This method constructs a new URI based on the scheme of the URI spec. + * QueryInterface can be used on the resulting URI object to obtain a more + * specific type of URI. */ nsIURI newURI(in AUTF8String aSpec, [optional] in string aOriginCharset, @@ -270,6 +283,35 @@ interface nsIIOService : nsISupports * The pid for socket process. */ readonly attribute unsigned long long socketProcessId; + + /** + * Register a protocol handler at runtime, given protocol flags and a + * default port. + * + * Statically registered protocol handlers cannot be overridden, and an + * error will be returned if that is attempted. + * + * Runtime registered protocol handlers are never QueryInterface-ed into + * `nsIProtocolHandlerWithDynamicFlags`, so that interface will be ignored. + * + * @param aScheme the scheme handled by the protocol handler. + * @param aHandler the protocol handler instance. + * @param aProtocolFlags protocol flags for this protocol, see + * nsIProtocolHandler for values. + * @param aDefaultPort default port for this scheme, or -1. + */ + void registerProtocolHandler(in ACString aScheme, + in nsIProtocolHandler aHandler, + in unsigned long aProtocolFlags, + in long aDefaultPort); + + /** + * Unregister a protocol handler which was previously registered using + * registerProtocolHandler. + * + * @param aScheme the scheme to unregister a handler for. + */ + void unregisterProtocolHandler(in ACString aScheme); }; %{C++ diff --git a/netwerk/base/nsIOService.cpp b/netwerk/base/nsIOService.cpp index c99050cf4847..de506f59a1f3 100644 --- a/netwerk/base/nsIOService.cpp +++ b/netwerk/base/nsIOService.cpp @@ -23,6 +23,7 @@ #include "nsNetCID.h" #include "nsCRT.h" #include "nsSimpleNestedURI.h" +#include "nsSocketTransport2.h" #include "nsTArray.h" #include "nsIConsoleService.h" #include "nsIUploadChannel2.h" @@ -64,10 +65,7 @@ #include "mozilla/StaticPrefs_security.h" #include "nsNSSComponent.h" #include "ssl.h" - -#ifdef MOZ_WIDGET_GTK -# include "nsGIOProtocolHandler.h" -#endif +#include "StaticComponents.h" namespace mozilla { namespace net { @@ -88,6 +86,7 @@ using mozilla::dom::ServiceWorkerDescriptor; #define NETWORK_CAPTIVE_PORTAL_PREF "network.captive-portal-service.enabled" #define WEBRTC_PREF_PREFIX "media.peerconnection." #define NETWORK_DNS_PREF "network.dns." +#define FORCE_EXTERNAL_PREF_PREFIX "network.protocol-handler.external." #define MAX_RECURSION_COUNT 50 @@ -213,6 +212,7 @@ static const char* gCallbackPrefs[] = { NECKO_BUFFER_CACHE_COUNT_PREF, NECKO_BUFFER_CACHE_SIZE_PREF, NETWORK_CAPTIVE_PORTAL_PREF, + FORCE_EXTERNAL_PREF_PREFIX, nullptr, }; @@ -846,121 +846,65 @@ nsresult nsIOService::AsyncOnChannelRedirect( return NS_OK; } -nsresult nsIOService::CacheProtocolHandler(const char* scheme, - nsIProtocolHandler* handler) { - MOZ_ASSERT(NS_IsMainThread()); - - for (unsigned int i = 0; i < NS_N(gScheme); i++) { - if (!nsCRT::strcasecmp(scheme, gScheme[i])) { - nsresult rv; - NS_ASSERTION(!mWeakHandler[i], "Protocol handler already cached"); - // Make sure the handler supports weak references. - nsCOMPtr factoryPtr = - do_QueryInterface(handler, &rv); - if (!factoryPtr) { - // Don't cache handlers that don't support weak reference as - // there is real danger of a circular reference. -#ifdef DEBUG_dp - printf( - "DEBUG: %s protcol handler doesn't support weak ref. Not cached.\n", - scheme); -#endif /* DEBUG_dp */ - return NS_ERROR_FAILURE; - } - mWeakHandler[i] = do_GetWeakReference(handler); - return NS_OK; - } - } - return NS_ERROR_FAILURE; -} - -nsresult nsIOService::GetCachedProtocolHandler(const char* scheme, - nsIProtocolHandler** result, - uint32_t start, uint32_t end) { - MOZ_ASSERT(NS_IsMainThread()); - - uint32_t len = end - start - 1; - for (unsigned int i = 0; i < NS_N(gScheme); i++) { - if (!mWeakHandler[i]) continue; - - // handle unterminated strings - // start is inclusive, end is exclusive, len = end - start - 1 - if (end ? (!nsCRT::strncasecmp(scheme + start, gScheme[i], len) && - gScheme[i][len] == '\0') - : (!nsCRT::strcasecmp(scheme, gScheme[i]))) { - return CallQueryReferent(mWeakHandler[i].get(), result); - } - } - return NS_ERROR_FAILURE; -} - -static bool UsesExternalProtocolHandler(const char* aScheme) { - if ("file"_ns.Equals(aScheme) || "chrome"_ns.Equals(aScheme) || - "resource"_ns.Equals(aScheme)) { +bool nsIOService::UsesExternalProtocolHandler(const nsACString& aScheme) { + if (aScheme == "file"_ns || aScheme == "chrome"_ns || + aScheme == "resource"_ns) { // Don't allow file:, chrome: or resource: URIs to be handled with // nsExternalProtocolHandler, since internally we rely on being able to // use and read from these URIs. return false; } - for (const auto& forcedExternalScheme : gForcedExternalSchemes) { - if (!nsCRT::strcasecmp(forcedExternalScheme, aScheme)) { + if (aScheme == "place"_ns || aScheme == "fake-favicon-uri"_ns || + aScheme == "favicon"_ns || aScheme == "moz-nullprincipal"_ns) { + // Force place: fake-favicon-uri: favicon: and moz-nullprincipal: URIs to be + // handled with nsExternalProtocolHandler, and not with a dynamically + // registered handler. + return true; + } + + // If prefs configure the URI to be handled externally, do so. + for (const auto& scheme : mForceExternalSchemes) { + if (aScheme == scheme) { return true; } } + return false; +} - nsAutoCString pref("network.protocol-handler.external."); - pref += aScheme; +ProtocolHandlerInfo nsIOService::LookupProtocolHandler( + const nsACString& aScheme) { + // Look-ups are ASCII-case-insensitive, so lower-case the string before + // continuing. + nsAutoCString scheme(aScheme); + ToLowerCase(scheme); - return Preferences::GetBool(pref.get(), false); + // NOTE: If we could get rid of mForceExternalSchemes (or prevent them from + // disabling static protocols), we could avoid locking mLock until we need to + // check `mRuntimeProtocolHandlers. + AutoReadLock lock(mLock); + if (!UsesExternalProtocolHandler(scheme)) { + // Try the static protocol handler first - they cannot be overridden by + // dynamic protocols. + if (const xpcom::StaticProtocolHandler* handler = + xpcom::StaticProtocolHandler::Lookup(scheme)) { + return ProtocolHandlerInfo(*handler); + } + if (auto handler = mRuntimeProtocolHandlers.Lookup(scheme)) { + return ProtocolHandlerInfo(handler.Data()); + } + } + return ProtocolHandlerInfo(xpcom::StaticProtocolHandler::Default()); } NS_IMETHODIMP nsIOService::GetProtocolHandler(const char* scheme, nsIProtocolHandler** result) { - nsresult rv; - + AssertIsOnMainThread(); NS_ENSURE_ARG_POINTER(scheme); - // XXX we may want to speed this up by introducing our own protocol - // scheme -> protocol handler mapping, avoiding the string manipulation - // and service manager stuff - rv = GetCachedProtocolHandler(scheme, result); - if (NS_SUCCEEDED(rv)) return rv; - - if (scheme[0] != '\0' && !UsesExternalProtocolHandler(scheme)) { - nsAutoCString contractID(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX); - contractID += scheme; - ToLowerCase(contractID); - - rv = CallGetService(contractID.get(), result); - if (NS_SUCCEEDED(rv)) { - CacheProtocolHandler(scheme, *result); - return rv; - } - -#ifdef MOZ_WIDGET_GTK - // check to see whether GVFS can handle this URI scheme. otherwise, we - // failover to using the default protocol handler. - - RefPtr gioHandler = - nsGIOProtocolHandler::GetSingleton(); - if (gioHandler->IsSupportedProtocol(nsCString(scheme))) { - gioHandler.forget(result); - return NS_OK; - } -#endif - } - - // Okay we don't have a protocol handler to handle this url type, so use - // the default protocol handler. This will cause urls to get dispatched - // out to the OS ('cause we can't do anything with them) when we try to - // read from a channel created by the default protocol handler. - - rv = CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "default", result); - if (NS_FAILED(rv)) return NS_ERROR_UNKNOWN_PROTOCOL; - - return rv; + *result = LookupProtocolHandler(nsDependentCString(scheme)).Handler().take(); + return *result ? NS_OK : NS_ERROR_UNKNOWN_PROTOCOL; } NS_IMETHODIMP @@ -1016,19 +960,32 @@ nsIOService::HostnameIsSharedIPAddress(nsIURI* aURI, bool* aResult) { NS_IMETHODIMP nsIOService::GetProtocolFlags(const char* scheme, uint32_t* flags) { - nsCOMPtr handler; - nsresult rv = GetProtocolHandler(scheme, getter_AddRefs(handler)); - if (NS_FAILED(rv)) return rv; + NS_ENSURE_ARG_POINTER(scheme); - // We can't call DoGetProtocolFlags here because we don't have a URI. This - // API is used by (and only used by) extensions, which is why it's still - // around. Calling this on a scheme with dynamic flags will throw. - rv = handler->GetProtocolFlags(flags); -#if !IS_ORIGIN_IS_FULL_SPEC_DEFINED - MOZ_RELEASE_ASSERT(!(*flags & nsIProtocolHandler::ORIGIN_IS_FULL_SPEC), - "ORIGIN_IS_FULL_SPEC is unsupported but used"); -#endif - return rv; + *flags = + LookupProtocolHandler(nsDependentCString(scheme)).StaticProtocolFlags(); + return NS_OK; +} + +NS_IMETHODIMP +nsIOService::GetDynamicProtocolFlags(nsIURI* uri, uint32_t* flags) { + AssertIsOnMainThread(); + NS_ENSURE_ARG(uri); + + nsAutoCString scheme; + nsresult rv = uri->GetScheme(scheme); + NS_ENSURE_SUCCESS(rv, rv); + + return LookupProtocolHandler(scheme).DynamicProtocolFlags(uri, flags); +} + +NS_IMETHODIMP +nsIOService::GetDefaultPort(const char* scheme, int32_t* defaultPort) { + NS_ENSURE_ARG_POINTER(scheme); + + *defaultPort = + LookupProtocolHandler(nsDependentCString(scheme)).DefaultPort(); + return NS_OK; } class AutoIncrement { @@ -1156,10 +1113,6 @@ nsresult nsIOService::NewChannelFromURIWithProxyFlagsInternal( rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler)); if (NS_FAILED(rv)) return rv; - uint32_t protoFlags; - rv = handler->DoGetProtocolFlags(aURI, &protoFlags); - if (NS_FAILED(rv)) return rv; - nsCOMPtr channel; nsCOMPtr pph = do_QueryInterface(handler); if (pph) { @@ -1464,7 +1417,7 @@ nsIOService::AllowPort(int32_t inPort, const char* scheme, bool* _retval) { nsTArray restrictedPortList; { - MutexAutoLock lock(mMutex); + AutoReadLock lock(mLock); restrictedPortList.Assign(mRestrictedPortList); } // first check to see if the port is in our blacklist: @@ -1558,13 +1511,30 @@ void nsIOService::PrefsChanged(const char* pref) { } } } + + if (!pref || strncmp(pref, FORCE_EXTERNAL_PREF_PREFIX, + strlen(FORCE_EXTERNAL_PREF_PREFIX)) == 0) { + nsTArray prefs; + if (nsIPrefBranch* prefRootBranch = Preferences::GetRootBranch()) { + prefRootBranch->GetChildList(FORCE_EXTERNAL_PREF_PREFIX, prefs); + } + nsTArray forceExternalSchemes; + for (const auto& pref : prefs) { + if (Preferences::GetBool(pref.get(), false)) { + forceExternalSchemes.AppendElement( + Substring(pref, strlen(FORCE_EXTERNAL_PREF_PREFIX))); + } + } + AutoWriteLock lock(mLock); + mForceExternalSchemes = std::move(forceExternalSchemes); + } } void nsIOService::ParsePortList(const char* pref, bool remove) { nsAutoCString portList; nsTArray restrictedPortList; { - MutexAutoLock lock(mMutex); + AutoWriteLock lock(mLock); restrictedPortList.Assign(std::move(mRestrictedPortList)); } // Get a pref string and chop it up into a list of ports. @@ -1605,7 +1575,7 @@ void nsIOService::ParsePortList(const char* pref, bool remove) { } } - MutexAutoLock lock(mMutex); + AutoWriteLock lock(mLock); mRestrictedPortList.Assign(std::move(restrictedPortList)); } @@ -1713,6 +1683,13 @@ nsIOService::Observe(nsISupports* subject, const char* topic, gCallbackSecurityPrefs, this); PrepareForShutdownInSocketProcess(); } + + // We're in XPCOM shutdown now. Unregister any dynamic protocol handlers + // after this point to avoid leaks. + { + AutoWriteLock lock(mLock); + mRuntimeProtocolHandlers.Clear(); + } } else if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) { OnNetworkLinkEvent(NS_ConvertUTF16toUTF8(data).get()); } else if (!strcmp(topic, NS_NETWORK_ID_CHANGED_TOPIC)) { @@ -1755,13 +1732,16 @@ nsIOService::ProtocolHasFlags(nsIURI* uri, uint32_t flags, bool* result) { nsresult rv = uri->GetScheme(scheme); NS_ENSURE_SUCCESS(rv, rv); - // Grab the protocol flags from the URI. + auto handler = LookupProtocolHandler(scheme); + uint32_t protocolFlags; - nsCOMPtr handler; - rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler)); - NS_ENSURE_SUCCESS(rv, rv); - rv = handler->DoGetProtocolFlags(uri, &protocolFlags); - NS_ENSURE_SUCCESS(rv, rv); + if (flags & nsIProtocolHandler::DYNAMIC_URI_FLAGS) { + AssertIsOnMainThread(); + rv = handler.DynamicProtocolFlags(uri, &protocolFlags); + NS_ENSURE_SUCCESS(rv, rv); + } else { + protocolFlags = handler.StaticProtocolFlags(); + } *result = (protocolFlags & flags) == flags; return NS_OK; @@ -2121,5 +2101,60 @@ nsIOService::GetSocketProcessId(uint64_t* aPid) { return NS_OK; } +NS_IMETHODIMP +nsIOService::RegisterProtocolHandler(const nsACString& aScheme, + nsIProtocolHandler* aHandler, + uint32_t aProtocolFlags, + int32_t aDefaultPort) { + if (mShutdown) { + return NS_ERROR_NOT_AVAILABLE; + } + if (aScheme.IsEmpty()) { + return NS_ERROR_INVALID_ARG; + } + + nsAutoCString scheme(aScheme); + ToLowerCase(scheme); + + AutoWriteLock lock(mLock); + return mRuntimeProtocolHandlers.WithEntryHandle(scheme, [&](auto&& entry) { + if (entry) { + NS_WARNING("Cannot override an existing dynamic protocol handler"); + return NS_ERROR_FACTORY_EXISTS; + } + if (xpcom::StaticProtocolHandler::Lookup(scheme)) { + NS_WARNING("Cannot override an existing static protocol handler"); + return NS_ERROR_FACTORY_EXISTS; + } + nsMainThreadPtrHandle handler( + new nsMainThreadPtrHolder("RuntimeProtocolHandler", + aHandler)); + entry.Insert(RuntimeProtocolHandler{ + .mHandler = std::move(handler), + .mProtocolFlags = aProtocolFlags, + .mDefaultPort = aDefaultPort, + }); + return NS_OK; + }); +} + +NS_IMETHODIMP +nsIOService::UnregisterProtocolHandler(const nsACString& aScheme) { + if (mShutdown) { + return NS_OK; + } + if (aScheme.IsEmpty()) { + return NS_ERROR_INVALID_ARG; + } + + nsAutoCString scheme(aScheme); + ToLowerCase(scheme); + + AutoWriteLock lock(mLock); + return mRuntimeProtocolHandlers.Remove(scheme) + ? NS_OK + : NS_ERROR_FACTORY_NOT_REGISTERED; +} + } // namespace net } // namespace mozilla diff --git a/netwerk/base/nsIOService.h b/netwerk/base/nsIOService.h index 206370d969e7..de6fe060fb1e 100644 --- a/netwerk/base/nsIOService.h +++ b/netwerk/base/nsIOService.h @@ -19,7 +19,8 @@ #include "nsWeakReference.h" #include "mozilla/Atomics.h" #include "mozilla/Attributes.h" -#include "mozilla/Mutex.h" +#include "mozilla/RWLock.h" +#include "mozilla/net/ProtocolHandlerInfo.h" #include "prtime.h" #include "nsICaptivePortalService.h" #include "nsIObserverService.h" @@ -35,14 +36,6 @@ #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline" #define NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC "ipc:network:set-connectivity" -static const char gScheme[][sizeof("moz-safe-about")] = { - "chrome", "file", "http", "https", - "jar", "data", "about", "moz-safe-about", - "resource", "moz-extension", "page-icon", "blob"}; - -static const char gForcedExternalSchemes[][sizeof("moz-nullprincipal")] = { - "place", "fake-favicon-uri", "favicon", "moz-nullprincipal"}; - class nsINetworkLinkService; class nsIPrefBranch; class nsIProtocolProxyService2; @@ -142,6 +135,10 @@ class nsIOService final : public nsIIOService, friend SocketProcessMemoryReporter; RefPtr GetSocketProcessMemoryReporter(); + // Lookup the ProtocolHandlerInfo based on a given scheme. + // Safe to call from any thread. + ProtocolHandlerInfo LookupProtocolHandler(const nsACString& aScheme); + static void OnTLSPrefChange(const char* aPref, void* aSelf); nsresult LaunchSocketProcess(); @@ -159,12 +156,6 @@ class nsIOService final : public nsIIOService, nsresult OnNetworkLinkEvent(const char* data); - nsresult GetCachedProtocolHandler(const char* scheme, - nsIProtocolHandler** hdlrResult, - uint32_t start = 0, uint32_t end = 0); - nsresult CacheProtocolHandler(const char* scheme, - nsIProtocolHandler* handler); - nsresult InitializeCaptivePortalService(); nsresult RecheckCaptivePortalIfLocalRedirect(nsIChannel* newChan); @@ -205,6 +196,9 @@ class nsIOService final : public nsIIOService, nsresult SetOfflineInternal(bool offline, bool notifySocketProcess = true); + bool UsesExternalProtocolHandler(const nsACString& aScheme) + MOZ_REQUIRES_SHARED(mLock); + private: mozilla::Atomic mOffline{true}; mozilla::Atomic mOfflineForProfileChange{false}; @@ -226,15 +220,15 @@ class nsIOService final : public nsIIOService, nsCOMPtr mNetworkLinkService; bool mNetworkLinkServiceInitialized{false}; - // Cached protocol handlers, only accessed on the main thread - nsWeakPtr mWeakHandler[NS_N(gScheme)]; - // cached categories nsCategoryCache mChannelEventSinks{ NS_CHANNEL_EVENT_SINK_CATEGORY}; - Mutex mMutex{"nsIOService::mMutex"}; - nsTArray mRestrictedPortList MOZ_GUARDED_BY(mMutex); + RWLock mLock{"nsIOService::mLock"}; + nsTArray mRestrictedPortList MOZ_GUARDED_BY(mLock); + nsTArray mForceExternalSchemes MOZ_GUARDED_BY(mLock); + nsTHashMap mRuntimeProtocolHandlers + MOZ_GUARDED_BY(mLock); uint32_t mTotalRequests{0}; uint32_t mCacheWon{0}; diff --git a/netwerk/base/nsIProtocolHandler.idl b/netwerk/base/nsIProtocolHandler.idl index ec19e8fe5f3b..adc4d2f960f4 100644 --- a/netwerk/base/nsIProtocolHandler.idl +++ b/netwerk/base/nsIProtocolHandler.idl @@ -37,6 +37,9 @@ interface nsIProtocolHandlerWithDynamicFlags : nsISupports /* * Returns protocol flags for the given URI, which may be different from the * flags for another URI of the same scheme. + * + * Only DYNAMIC_URI_FLAGS may be different from the registered flags for the + * protocol handler. */ unsigned long getFlagsForURI(in nsIURI aURI); }; @@ -112,6 +115,10 @@ interface nsIProtocolHandler : nsISupports * Constants for the protocol flags (the first is the default mask, the * others are deviations): * + * NOTE: Protocol flags are provided when the protocol handler is + * registered, either through a static component or dynamically with + * `nsIIOService.registerProtocolHandler`. + * * NOTE: Implementation must ignore any flags they do not understand. */ @@ -331,7 +338,8 @@ interface nsIProtocolHandler : nsISupports * Flags which are allowed to be different from the static flags when * returned from `nsIProtocolHandlerWithDynamicFlags::getFlagsForURI`. * - * All other flags must match the `protocolFlags` attribute. + * All other flags must match the flags provided when the protocol handler + * was registered. */ const unsigned long DYNAMIC_URI_FLAGS = URI_LOADABLE_BY_ANYONE | URI_DANGEROUS_TO_LOAD | diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp index fa111f5328a4..249a200ce3be 100644 --- a/netwerk/base/nsNetUtil.cpp +++ b/netwerk/base/nsNetUtil.cpp @@ -17,6 +17,7 @@ #include "mozilla/LoadContext.h" #include "mozilla/LoadInfo.h" #include "mozilla/Monitor.h" +#include "mozilla/StaticPrefs_browser.h" #include "mozilla/StaticPrefs_network.h" #include "mozilla/StaticPrefs_privacy.h" #include "mozilla/StoragePrincipalHelper.h" @@ -26,6 +27,7 @@ #include "nsCategoryCache.h" #include "nsComponentManagerUtils.h" #include "nsContentUtils.h" +#include "nsEscape.h" #include "nsFileStreams.h" #include "nsHashKeys.h" #include "nsHttp.h" @@ -666,9 +668,11 @@ int32_t NS_GetDefaultPort(const char* scheme, nsIIOService* ioService /* = nullptr */) { nsresult rv; - // Getting the default port through the protocol handler has a lot of XPCOM - // overhead involved. We optimize the protocols that matter for Web pages - // (HTTP and HTTPS) by hardcoding their default ports here. + // Getting the default port through the protocol handler previously had a lot + // of XPCOM overhead involved. We optimize the protocols that matter for Web + // pages (HTTP and HTTPS) by hardcoding their default ports here. + // + // XXX: This might not be necessary for performance anymore. if (strncmp(scheme, "http", 4) == 0) { if (scheme[4] == 's' && scheme[5] == '\0') { return 443; @@ -682,11 +686,8 @@ int32_t NS_GetDefaultPort(const char* scheme, net_EnsureIOService(&ioService, grip); if (!ioService) return -1; - nsCOMPtr handler; - rv = ioService->GetProtocolHandler(scheme, getter_AddRefs(handler)); - if (NS_FAILED(rv)) return -1; int32_t port; - rv = handler->GetDefaultPort(&port); + rv = ioService->GetDefaultPort(scheme, &port); return NS_SUCCEEDED(rv) ? port : -1; } diff --git a/netwerk/base/nsProtocolProxyService.cpp b/netwerk/base/nsProtocolProxyService.cpp index c9096194aa56..da42cb588b7e 100644 --- a/netwerk/base/nsProtocolProxyService.cpp +++ b/netwerk/base/nsProtocolProxyService.cpp @@ -2017,6 +2017,7 @@ void nsProtocolProxyService::LoadHostFilters(const nsACString& aFilters) { nsresult nsProtocolProxyService::GetProtocolInfo(nsIURI* uri, nsProtocolInfo* info) { + AssertIsOnMainThread(); MOZ_ASSERT(uri, "URI is null"); MOZ_ASSERT(info, "info is null"); @@ -2028,14 +2029,10 @@ nsresult nsProtocolProxyService::GetProtocolInfo(nsIURI* uri, nsCOMPtr ios = do_GetIOService(&rv); if (NS_FAILED(rv)) return rv; - nsCOMPtr handler; - rv = ios->GetProtocolHandler(info->scheme.get(), getter_AddRefs(handler)); + rv = ios->GetDynamicProtocolFlags(uri, &info->flags); if (NS_FAILED(rv)) return rv; - rv = handler->DoGetProtocolFlags(uri, &info->flags); - if (NS_FAILED(rv)) return rv; - - rv = handler->GetDefaultPort(&info->defaultPort); + rv = ios->GetDefaultPort(info->scheme.get(), &info->defaultPort); return rv; } diff --git a/netwerk/test/browser/browser_nsIFormPOSTActionChannel.js b/netwerk/test/browser/browser_nsIFormPOSTActionChannel.js index d478a75528c9..048bb6d6aa61 100644 --- a/netwerk/test/browser/browser_nsIFormPOSTActionChannel.js +++ b/netwerk/test/browser/browser_nsIFormPOSTActionChannel.js @@ -23,15 +23,6 @@ CustomProtocolHandler.prototype = { get scheme() { return SCHEME; }, - get defaultPort() { - return -1; - }, - get protocolFlags() { - return ( - Ci.nsIProtocolHandler.URI_NORELATIVE | - Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE - ); - }, newChannel(aURI, aLoadInfo) { return new CustomChannel(aURI, aLoadInfo); }, @@ -39,14 +30,8 @@ CustomProtocolHandler.prototype = { return port != -1; }, - /** nsIFactory */ - createInstance(aIID) { - return this.QueryInterface(aIID); - }, - /** nsISupports */ - QueryInterface: ChromeUtils.generateQI(["nsIProtocolHandler", "nsIFactory"]), - classID: Components.ID("{16d594bc-d9d8-47ae-a139-ea714dc0c35c}"), + QueryInterface: ChromeUtils.generateQI(["nsIProtocolHandler"]), }; function CustomChannel(aURI, aLoadInfo) { @@ -250,15 +235,15 @@ function loadTestTab(uri) { add_task(async function() { var handler = new CustomProtocolHandler(); - var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); - registrar.registerFactory( - handler.classID, - "", - "@mozilla.org/network/protocol;1?name=" + handler.scheme, - handler + Services.io.registerProtocolHandler( + SCHEME, + handler, + Ci.nsIProtocolHandler.URI_NORELATIVE | + Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE, + -1 ); registerCleanupFunction(function() { - registrar.unregisterFactory(handler.classID, handler); + Services.io.unregisterProtocolHandler(SCHEME); }); }); diff --git a/netwerk/test/unit/test_bug894586.js b/netwerk/test/unit/test_bug894586.js index 5ba9687545e4..bc25731d3610 100644 --- a/netwerk/test/unit/test_bug894586.js +++ b/netwerk/test/unit/test_bug894586.js @@ -21,19 +21,6 @@ ProtocolHandler.prototype = { get scheme() { return "x-bug894586"; }, - get defaultPort() { - return -1; - }, - get protocolFlags() { - return ( - Ci.nsIProtocolHandler.URI_NORELATIVE | - Ci.nsIProtocolHandler.URI_NOAUTH | - Ci.nsIProtocolHandler.URI_IS_UI_RESOURCE | - Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE | - Ci.nsIProtocolHandler.URI_NON_PERSISTABLE | - Ci.nsIProtocolHandler.URI_SYNC_LOAD_IS_OK - ); - }, newChannel(aURI, aLoadInfo) { this.loadInfo = aLoadInfo; return this; @@ -106,19 +93,12 @@ ProtocolHandler.prototype = { Ci.nsIRequest.INHIBIT_CACHING | Ci.nsIRequest.LOAD_BYPASS_CACHE, - /** nsIFactory */ - createInstance(aIID) { - return this.QueryInterface(aIID); - }, - /** nsISupports */ QueryInterface: ChromeUtils.generateQI([ "nsIProtocolHandler", "nsIRequest", "nsIChannel", - "nsIFactory", ]), - classID: Components.ID("{16d594bc-d9d8-47ae-a139-ea714dc0c35c}"), }; /** @@ -127,12 +107,17 @@ ProtocolHandler.prototype = { */ function run_test() { var handler = new ProtocolHandler(); - var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); - registrar.registerFactory( - handler.classID, - "", - "@mozilla.org/network/protocol;1?name=" + handler.scheme, - handler + + Services.io.registerProtocolHandler( + handler.scheme, + handler, + Ci.nsIProtocolHandler.URI_NORELATIVE | + Ci.nsIProtocolHandler.URI_NOAUTH | + Ci.nsIProtocolHandler.URI_IS_UI_RESOURCE | + Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE | + Ci.nsIProtocolHandler.URI_NON_PERSISTABLE | + Ci.nsIProtocolHandler.URI_SYNC_LOAD_IS_OK, + -1 ); try { var ss = Cc["@mozilla.org/content/style-sheet-service;1"].getService( @@ -143,7 +128,7 @@ function run_test() { ss.sheetRegistered(handler.uri, Ci.nsIStyleSheetService.AGENT_SHEET) ); } finally { - registrar.unregisterFactory(handler.classID, handler); + Services.io.unregisterProtocolHandler(handler.scheme); } } diff --git a/remote/shared/webdriver/Capabilities.sys.mjs b/remote/shared/webdriver/Capabilities.sys.mjs index 715ba9565f74..7a1552746d5d 100644 --- a/remote/shared/webdriver/Capabilities.sys.mjs +++ b/remote/shared/webdriver/Capabilities.sys.mjs @@ -249,7 +249,7 @@ export class Proxy { if (scheme === "socks") { port = null; } else { - port = Services.io.getProtocolHandler(scheme).defaultPort; + port = Services.io.getDefaultPort(scheme); } } diff --git a/toolkit/components/backgroundtasks/tests/browser/browser_xpcom_graph_wait.js b/toolkit/components/backgroundtasks/tests/browser/browser_xpcom_graph_wait.js index 4d3429997b53..3a0b77db93d0 100644 --- a/toolkit/components/backgroundtasks/tests/browser/browser_xpcom_graph_wait.js +++ b/toolkit/components/backgroundtasks/tests/browser/browser_xpcom_graph_wait.js @@ -66,7 +66,6 @@ const backgroundtaskPhases = { "@mozilla.org/network/idn-service;1", "@mozilla.org/network/io-service;1", "@mozilla.org/network/network-link-service;1", - "@mozilla.org/network/protocol;1?name=chrome", "@mozilla.org/network/protocol;1?name=file", "@mozilla.org/network/protocol;1?name=jar", "@mozilla.org/network/protocol;1?name=resource", diff --git a/toolkit/components/downloads/DownloadPlatform.cpp b/toolkit/components/downloads/DownloadPlatform.cpp index 3beab18bc531..ee2e0a3248f0 100644 --- a/toolkit/components/downloads/DownloadPlatform.cpp +++ b/toolkit/components/downloads/DownloadPlatform.cpp @@ -290,22 +290,10 @@ bool DownloadPlatform::IsURLPossiblyFromWeb(nsIURI* aURI) { } while (uri) { - // We're not using nsIIOService::ProtocolHasFlags because it doesn't - // take per-URI flags into account. We're also not using - // NS_URIChainHasFlags because we're checking for *any* of 3 flags - // to be present on *all* of the nested URIs, which it can't do. - nsAutoCString scheme; - nsresult rv = uri->GetScheme(scheme); - if (NS_FAILED(rv)) { - return true; - } - nsCOMPtr ph; - rv = ios->GetProtocolHandler(scheme.get(), getter_AddRefs(ph)); - if (NS_FAILED(rv)) { - return true; - } + // We're not using NS_URIChainHasFlags because we're checking for *any* of 3 + // flags to be present on *all* of the nested URIs, which it can't do. uint32_t flags; - rv = ph->DoGetProtocolFlags(uri, &flags); + nsresult rv = ios->GetDynamicProtocolFlags(uri, &flags); if (NS_FAILED(rv)) { return true; } diff --git a/toolkit/components/extensions/MatchURLFilters.jsm b/toolkit/components/extensions/MatchURLFilters.jsm index 7dc6fe8e08d0..323614865845 100644 --- a/toolkit/components/extensions/MatchURLFilters.jsm +++ b/toolkit/components/extensions/MatchURLFilters.jsm @@ -83,7 +83,7 @@ class MatchURLFilters { if (["resource", "chrome"].includes(uri.scheme)) { port = undefined; } else { - port = Services.io.getProtocolHandler(uri.scheme).defaultPort; + port = Services.io.getDefaultPort(uri.scheme); } }