Bug 1186152 - Implement nsIProtocolHandlerWithDynamicFlags and use it for moz-extension. r=bz

This commit is contained in:
Bobby Holley 2015-07-27 13:27:38 -07:00
parent 6fdff0800a
commit 4fefff8e42
9 changed files with 95 additions and 33 deletions

View File

@ -761,16 +761,6 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
// the methods that work on chains of nested URIs and they will only look
// at the flags for our one URI.
// Special case: moz-extension has a whitelist of URIs that are loadable by
// anyone.
if (targetScheme.EqualsLiteral("moz-extension") && GetAddonPolicyService()) {
bool loadable = false;
rv = GetAddonPolicyService()->ExtensionURILoadableByAnyone(targetBaseURI, &loadable);
if (NS_SUCCEEDED(rv) && loadable) {
return NS_OK;
}
}
// Check for system target URI
rv = DenyAccessIfURIHasFlags(targetBaseURI,
nsIProtocolHandler::URI_DANGEROUS_TO_LOAD);

View File

@ -104,7 +104,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1161831
} catch (e) {
ifr.remove();
threw = true;
ok(/denied|insecure/.test(e), "exceiton correct: " + e);
ok(/denied|insecure/.test(e), "exception correct: " + e);
}
is(threw, !!shouldThrow, "Correct throwing behavior for: " + url);
!threw || resolve();

View File

@ -557,6 +557,9 @@ nsIOService::GetProtocolFlags(const char* scheme, uint32_t *flags)
nsresult rv = GetProtocolHandler(scheme, getter_AddRefs(handler));
if (NS_FAILED(rv)) return rv;
// 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);
return rv;
}
@ -722,7 +725,7 @@ nsIOService::NewChannelFromURIWithProxyFlagsInternal(nsIURI* aURI,
return rv;
uint32_t protoFlags;
rv = handler->GetProtocolFlags(&protoFlags);
rv = handler->DoGetProtocolFlags(aURI, &protoFlags);
if (NS_FAILED(rv))
return rv;
@ -1481,15 +1484,17 @@ nsIOService::ProtocolHasFlags(nsIURI *uri,
nsAutoCString scheme;
nsresult rv = uri->GetScheme(scheme);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t protocolFlags;
rv = GetProtocolFlags(scheme.get(), &protocolFlags);
if (NS_SUCCEEDED(rv)) {
*result = (protocolFlags & flags) == flags;
}
return rv;
// Grab the protocol flags from the URI.
uint32_t protocolFlags;
nsCOMPtr<nsIProtocolHandler> handler;
rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
NS_ENSURE_SUCCESS(rv, rv);
rv = handler->DoGetProtocolFlags(uri, &protocolFlags);
NS_ENSURE_SUCCESS(rv, rv);
*result = (protocolFlags & flags) == flags;
return NS_OK;
}
NS_IMETHODIMP

View File

@ -5,14 +5,34 @@
#include "nsISupports.idl"
%{C++
#include "nsCOMPtr.h"
%}
interface nsIURI;
interface nsIChannel;
interface nsILoadInfo;
/**
* nsIProtocolHandlerWithDynamicFlags
*
* Protocols that wish to return different flags depending on the URI should
* implement this interface.
*/
[scriptable, builtinclass, uuid(65a8e823-0591-4fc0-a56a-03265e0a4ce8)]
interface nsIProtocolHandlerWithDynamicFlags : nsISupports
{
/*
* Returns protocol flags for the given URI, which may be different from the
* flags for another URI of the same scheme.
*/
unsigned long getFlagsForURI(in nsIURI aURI);
};
/**
* nsIProtocolHandler
*/
[scriptable, uuid(a7aad716-e72c-435d-82f1-7582dffae661)]
[scriptable, uuid(3393c327-ce70-47f1-9be3-cc312e21c012)]
interface nsIProtocolHandler : nsISupports
{
/**
@ -32,6 +52,15 @@ interface nsIProtocolHandler : nsISupports
*/
readonly attribute unsigned long protocolFlags;
%{C++
// Helper method to get the protocol flags in the right way.
nsresult DoGetProtocolFlags(nsIURI* aURI, uint32_t* aFlags)
{
nsCOMPtr<nsIProtocolHandlerWithDynamicFlags> dh = do_QueryInterface(this);
return dh ? dh->GetFlagsForURI(aURI, aFlags) : GetProtocolFlags(aFlags);
}
%}
/**
* Makes a URI object that is suitable for loading by this protocol,
* where the URI string is given as an UTF-8 string. The caller may
@ -258,8 +287,6 @@ interface nsIProtocolHandler : nsISupports
* by nsMixedContentBlocker
*/
const unsigned long URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT = (1<<18);
};
%{C++

View File

@ -1663,7 +1663,7 @@ nsProtocolProxyService::GetProtocolInfo(nsIURI *uri, nsProtocolInfo *info)
if (NS_FAILED(rv))
return rv;
rv = handler->GetProtocolFlags(&info->flags);
rv = handler->DoGetProtocolFlags(uri, &info->flags);
if (NS_FAILED(rv))
return rv;

View File

@ -6,11 +6,31 @@
#include "ExtensionProtocolHandler.h"
#include "nsIAddonPolicyService.h"
#include "nsServiceManagerUtils.h"
namespace mozilla {
NS_IMPL_QUERY_INTERFACE(ExtensionProtocolHandler, nsISubstitutingProtocolHandler,
nsIProtocolHandler, nsISupportsWeakReference)
nsIProtocolHandler, nsIProtocolHandlerWithDynamicFlags,
nsISupportsWeakReference)
NS_IMPL_ADDREF_INHERITED(ExtensionProtocolHandler, SubstitutingProtocolHandler)
NS_IMPL_RELEASE_INHERITED(ExtensionProtocolHandler, SubstitutingProtocolHandler)
nsresult
ExtensionProtocolHandler::GetFlagsForURI(nsIURI* aURI, uint32_t* aFlags)
{
// In general a moz-extension URI is only loadable by chrome, but a whitelisted
// subset are web-accessible. Check that whitelist.
nsCOMPtr<nsIAddonPolicyService> aps = do_GetService("@mozilla.org/addons/policy-service;1");
bool loadableByAnyone = false;
if (aps) {
nsresult rv = aps->ExtensionURILoadableByAnyone(aURI, &loadableByAnyone);
NS_ENSURE_SUCCESS(rv, rv);
}
*aFlags = URI_STD | URI_IS_LOCAL_RESOURCE | (loadableByAnyone ? URI_LOADABLE_BY_ANYONE : URI_DANGEROUS_TO_LOAD);
return NS_OK;
}
} // namespace mozilla

View File

@ -12,19 +12,17 @@
namespace mozilla {
class ExtensionProtocolHandler final : public nsISubstitutingProtocolHandler,
public nsIProtocolHandlerWithDynamicFlags,
public mozilla::SubstitutingProtocolHandler,
public nsSupportsWeakReference
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIPROTOCOLHANDLERWITHDYNAMICFLAGS
NS_FORWARD_NSIPROTOCOLHANDLER(mozilla::SubstitutingProtocolHandler::)
NS_FORWARD_NSISUBSTITUTINGPROTOCOLHANDLER(mozilla::SubstitutingProtocolHandler::)
// In general a moz-extension URI is only loadable by chrome, but a whitelisted
// subset are web-accessible (see nsIAddonPolicyService).
ExtensionProtocolHandler()
: SubstitutingProtocolHandler("moz-extension", URI_STD | URI_DANGEROUS_TO_LOAD | URI_IS_LOCAL_RESOURCE)
{}
ExtensionProtocolHandler() : SubstitutingProtocolHandler("moz-extension") {}
protected:
~ExtensionProtocolHandler() {}

View File

@ -84,9 +84,23 @@ SubstitutingURL::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
SubstitutingProtocolHandler::SubstitutingProtocolHandler(const char* aScheme, uint32_t aFlags,
bool aEnforceFileOrJar)
: mScheme(aScheme)
, mFlags(aFlags)
, mSubstitutions(16)
, mEnforceFileOrJar(aEnforceFileOrJar)
{
mFlags.emplace(aFlags);
ConstructInternal();
}
SubstitutingProtocolHandler::SubstitutingProtocolHandler(const char* aScheme)
: mScheme(aScheme)
, mSubstitutions(16)
, mEnforceFileOrJar(true)
{
ConstructInternal();
}
void
SubstitutingProtocolHandler::ConstructInternal()
{
nsresult rv;
mIOService = do_GetIOService(&rv);
@ -180,7 +194,12 @@ SubstitutingProtocolHandler::GetDefaultPort(int32_t *result)
nsresult
SubstitutingProtocolHandler::GetProtocolFlags(uint32_t *result)
{
*result = mFlags;
if (mFlags.isNothing()) {
NS_WARNING("Trying to get protocol flags the wrong way - use nsIProtocolHandlerWithDynamicFlags instead");
return NS_ERROR_NOT_AVAILABLE;
}
*result = mFlags.ref();
return NS_OK;
}

View File

@ -13,6 +13,7 @@
#include "nsIOService.h"
#include "nsStandardURL.h"
#include "mozilla/chrome/RegistryMessageUtils.h"
#include "mozilla/Maybe.h"
class nsIIOService;
@ -27,6 +28,7 @@ class SubstitutingProtocolHandler
{
public:
SubstitutingProtocolHandler(const char* aScheme, uint32_t aFlags, bool aEnforceFileOrJar = true);
explicit SubstitutingProtocolHandler(const char* aScheme);
NS_INLINE_DECL_REFCOUNTING(SubstitutingProtocolHandler);
NS_DECL_NON_VIRTUAL_NSIPROTOCOLHANDLER;
@ -36,6 +38,7 @@ public:
protected:
virtual ~SubstitutingProtocolHandler() {}
void ConstructInternal();
void SendSubstitution(const nsACString& aRoot, nsIURI* aBaseURI);
@ -51,7 +54,7 @@ protected:
private:
nsCString mScheme;
uint32_t mFlags;
Maybe<uint32_t> mFlags;
nsInterfaceHashtable<nsCStringHashKey,nsIURI> mSubstitutions;
nsCOMPtr<nsIIOService> mIOService;