mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1161831 - Factor the sharable bits out of nsIResProtocolHandler. r=billm
This commit is contained in:
parent
0e05c105f8
commit
42723b4796
@ -39,14 +39,16 @@ struct ChromePackage
|
||||
}
|
||||
};
|
||||
|
||||
struct ResourceMapping
|
||||
struct SubstitutionMapping
|
||||
{
|
||||
nsCString resource;
|
||||
nsCString scheme;
|
||||
nsCString path;
|
||||
SerializedURI resolvedURI;
|
||||
|
||||
bool operator ==(const ResourceMapping& rhs) const
|
||||
bool operator ==(const SubstitutionMapping& rhs) const
|
||||
{
|
||||
return resource.Equals(rhs.resource) &&
|
||||
return scheme.Equals(rhs.scheme) &&
|
||||
path.Equals(rhs.path) &&
|
||||
resolvedURI == rhs.resolvedURI;
|
||||
}
|
||||
};
|
||||
@ -134,24 +136,27 @@ struct ParamTraits<ChromePackage>
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<ResourceMapping>
|
||||
struct ParamTraits<SubstitutionMapping>
|
||||
{
|
||||
typedef ResourceMapping paramType;
|
||||
typedef SubstitutionMapping paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.resource);
|
||||
WriteParam(aMsg, aParam.scheme);
|
||||
WriteParam(aMsg, aParam.path);
|
||||
WriteParam(aMsg, aParam.resolvedURI);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
nsCString resource;
|
||||
nsCString scheme, path;
|
||||
SerializedURI resolvedURI;
|
||||
|
||||
if (ReadParam(aMsg, aIter, &resource) &&
|
||||
if (ReadParam(aMsg, aIter, &scheme) &&
|
||||
ReadParam(aMsg, aIter, &path) &&
|
||||
ReadParam(aMsg, aIter, &resolvedURI)) {
|
||||
aResult->resource = resource;
|
||||
aResult->scheme = scheme;
|
||||
aResult->path = path;
|
||||
aResult->resolvedURI = resolvedURI;
|
||||
return true;
|
||||
}
|
||||
@ -160,7 +165,9 @@ struct ParamTraits<ResourceMapping>
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
aLog->append(StringPrintf(L"[%s, %s, %u]", aParam.resource.get(),
|
||||
aLog->append(StringPrintf(L"[%s://%s, %s, %u]",
|
||||
aParam.scheme.get(),
|
||||
aParam.path.get(),
|
||||
aParam.resolvedURI.spec.get()));
|
||||
}
|
||||
};
|
||||
|
@ -445,7 +445,7 @@ nsChromeRegistryChrome::SendRegisteredChrome(
|
||||
mozilla::dom::PContentParent* aParent)
|
||||
{
|
||||
InfallibleTArray<ChromePackage> packages;
|
||||
InfallibleTArray<ResourceMapping> resources;
|
||||
InfallibleTArray<SubstitutionMapping> resources;
|
||||
InfallibleTArray<OverrideMapping> overrides;
|
||||
|
||||
EnumerationArgs args = {
|
||||
|
@ -17,7 +17,7 @@ nsChromeRegistryContent::nsChromeRegistryContent()
|
||||
void
|
||||
nsChromeRegistryContent::RegisterRemoteChrome(
|
||||
const InfallibleTArray<ChromePackage>& aPackages,
|
||||
const InfallibleTArray<ResourceMapping>& aResources,
|
||||
const InfallibleTArray<SubstitutionMapping>& aSubstitutions,
|
||||
const InfallibleTArray<OverrideMapping>& aOverrides,
|
||||
const nsACString& aLocale,
|
||||
bool aReset)
|
||||
@ -36,9 +36,9 @@ nsChromeRegistryContent::RegisterRemoteChrome(
|
||||
RegisterPackage(aPackages[i]);
|
||||
}
|
||||
|
||||
for (uint32_t i = aResources.Length(); i > 0; ) {
|
||||
for (uint32_t i = aSubstitutions.Length(); i > 0; ) {
|
||||
--i;
|
||||
RegisterResource(aResources[i]);
|
||||
RegisterSubstitution(aSubstitutions[i]);
|
||||
}
|
||||
|
||||
for (uint32_t i = aOverrides.Length(); i > 0; ) {
|
||||
@ -94,32 +94,32 @@ nsChromeRegistryContent::RegisterPackage(const ChromePackage& aPackage)
|
||||
}
|
||||
|
||||
void
|
||||
nsChromeRegistryContent::RegisterResource(const ResourceMapping& aResource)
|
||||
nsChromeRegistryContent::RegisterSubstitution(const SubstitutionMapping& aSubstitution)
|
||||
{
|
||||
nsCOMPtr<nsIIOService> io (do_GetIOService());
|
||||
if (!io)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIProtocolHandler> ph;
|
||||
nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
|
||||
nsresult rv = io->GetProtocolHandler(aSubstitution.scheme.get(), getter_AddRefs(ph));
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIResProtocolHandler> rph (do_QueryInterface(ph));
|
||||
if (!rph)
|
||||
nsCOMPtr<nsISubstitutingProtocolHandler> sph (do_QueryInterface(ph));
|
||||
if (!sph)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIURI> resolvedURI;
|
||||
if (aResource.resolvedURI.spec.Length()) {
|
||||
if (aSubstitution.resolvedURI.spec.Length()) {
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(resolvedURI),
|
||||
aResource.resolvedURI.spec,
|
||||
aResource.resolvedURI.charset.get(),
|
||||
aSubstitution.resolvedURI.spec,
|
||||
aSubstitution.resolvedURI.charset.get(),
|
||||
nullptr, io);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
}
|
||||
|
||||
rv = rph->SetSubstitution(aResource.resource, resolvedURI);
|
||||
rv = sph->SetSubstitution(aSubstitution.path, resolvedURI);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "nsClassHashtable.h"
|
||||
|
||||
struct ChromePackage;
|
||||
struct ResourceMapping;
|
||||
struct SubstitutionMapping;
|
||||
struct OverrideMapping;
|
||||
|
||||
class nsChromeRegistryContent : public nsChromeRegistry
|
||||
@ -19,7 +19,7 @@ class nsChromeRegistryContent : public nsChromeRegistry
|
||||
nsChromeRegistryContent();
|
||||
|
||||
void RegisterRemoteChrome(const InfallibleTArray<ChromePackage>& aPackages,
|
||||
const InfallibleTArray<ResourceMapping>& aResources,
|
||||
const InfallibleTArray<SubstitutionMapping>& aResources,
|
||||
const InfallibleTArray<OverrideMapping>& aOverrides,
|
||||
const nsACString& aLocale,
|
||||
bool aReset);
|
||||
@ -41,7 +41,7 @@ class nsChromeRegistryContent : public nsChromeRegistry
|
||||
|
||||
void RegisterPackage(const ChromePackage& aPackage);
|
||||
void RegisterOverride(const OverrideMapping& aOverride);
|
||||
void RegisterResource(const ResourceMapping& aResource);
|
||||
void RegisterSubstitution(const SubstitutionMapping& aResource);
|
||||
|
||||
private:
|
||||
struct PackageEntry
|
||||
|
@ -1838,7 +1838,7 @@ ContentChild::DeallocPWebrtcGlobalChild(PWebrtcGlobalChild *aActor)
|
||||
|
||||
bool
|
||||
ContentChild::RecvRegisterChrome(InfallibleTArray<ChromePackage>&& packages,
|
||||
InfallibleTArray<ResourceMapping>&& resources,
|
||||
InfallibleTArray<SubstitutionMapping>&& resources,
|
||||
InfallibleTArray<OverrideMapping>&& overrides,
|
||||
const nsCString& locale,
|
||||
const bool& reset)
|
||||
@ -1866,8 +1866,8 @@ ContentChild::RecvRegisterChromeItem(const ChromeRegistryItem& item)
|
||||
chromeRegistry->RegisterOverride(item.get_OverrideMapping());
|
||||
break;
|
||||
|
||||
case ChromeRegistryItem::TResourceMapping:
|
||||
chromeRegistry->RegisterResource(item.get_ResourceMapping());
|
||||
case ChromeRegistryItem::TSubstitutionMapping:
|
||||
chromeRegistry->RegisterSubstitution(item.get_SubstitutionMapping());
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
struct ChromePackage;
|
||||
class nsIObserver;
|
||||
struct ResourceMapping;
|
||||
struct SubstitutionMapping;
|
||||
struct OverrideMapping;
|
||||
class nsIDomainPolicy;
|
||||
|
||||
@ -282,7 +282,7 @@ public:
|
||||
virtual bool DeallocPSpeechSynthesisChild(PSpeechSynthesisChild* aActor) override;
|
||||
|
||||
virtual bool RecvRegisterChrome(InfallibleTArray<ChromePackage>&& packages,
|
||||
InfallibleTArray<ResourceMapping>&& resources,
|
||||
InfallibleTArray<SubstitutionMapping>&& resources,
|
||||
InfallibleTArray<OverrideMapping>&& overrides,
|
||||
const nsCString& locale,
|
||||
const bool& reset) override;
|
||||
|
@ -71,7 +71,7 @@ include "mozilla/dom/indexedDB/SerializationHelpers.h";
|
||||
using GeoPosition from "nsGeoPositionIPCSerialiser.h";
|
||||
|
||||
using struct ChromePackage from "mozilla/chrome/RegistryMessageUtils.h";
|
||||
using struct ResourceMapping from "mozilla/chrome/RegistryMessageUtils.h";
|
||||
using struct SubstitutionMapping from "mozilla/chrome/RegistryMessageUtils.h";
|
||||
using struct OverrideMapping from "mozilla/chrome/RegistryMessageUtils.h";
|
||||
using base::ChildPrivileges from "base/process_util.h";
|
||||
using base::ProcessId from "base/process.h";
|
||||
@ -94,7 +94,7 @@ union ChromeRegistryItem
|
||||
{
|
||||
ChromePackage;
|
||||
OverrideMapping;
|
||||
ResourceMapping;
|
||||
SubstitutionMapping;
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
@ -521,7 +521,7 @@ child:
|
||||
|
||||
PTestShell();
|
||||
|
||||
RegisterChrome(ChromePackage[] packages, ResourceMapping[] resources,
|
||||
RegisterChrome(ChromePackage[] packages, SubstitutionMapping[] substitutions,
|
||||
OverrideMapping[] overrides, nsCString locale, bool reset);
|
||||
RegisterChromeItem(ChromeRegistryItem item);
|
||||
|
||||
|
@ -637,15 +637,13 @@
|
||||
{0x8c, 0xda, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
|
||||
}
|
||||
|
||||
#define NS_RESURL_CID \
|
||||
{ /* ff8fe7ec-2f74-4408-b742-6b7a546029a8 */ \
|
||||
0xff8fe7ec, \
|
||||
0x2f74, \
|
||||
0x4408, \
|
||||
{0xb7, 0x42, 0x6b, 0x7a, 0x54, 0x60, 0x29, 0xa8} \
|
||||
#define NS_SUBSTITUTINGURL_CID \
|
||||
{ 0xdea9657c, \
|
||||
0x18cf, \
|
||||
0x4984, \
|
||||
{ 0xbd, 0xe9, 0xcc, 0xef, 0x5d, 0x8a, 0xb4, 0x73 } \
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* netwerk/protocol/file/ classes
|
||||
*/
|
||||
|
@ -272,8 +272,12 @@ namespace net {
|
||||
#ifdef NECKO_PROTOCOL_res
|
||||
// resource
|
||||
#include "nsResProtocolHandler.h"
|
||||
#include "SubstitutingProtocolHandler.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsResProtocolHandler, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsResURL)
|
||||
|
||||
namespace mozilla {
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(SubstitutingURL)
|
||||
} // namespace mozilla
|
||||
#endif
|
||||
|
||||
#ifdef NECKO_PROTOCOL_device
|
||||
@ -756,7 +760,7 @@ NS_DEFINE_NAMED_CID(NS_FTPPROTOCOLHANDLER_CID);
|
||||
#endif
|
||||
#ifdef NECKO_PROTOCOL_res
|
||||
NS_DEFINE_NAMED_CID(NS_RESPROTOCOLHANDLER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_RESURL_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SUBSTITUTINGURL_CID);
|
||||
#endif
|
||||
NS_DEFINE_NAMED_CID(NS_ABOUTPROTOCOLHANDLER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SAFEABOUTPROTOCOLHANDLER_CID);
|
||||
@ -902,7 +906,7 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
|
||||
#endif
|
||||
#ifdef NECKO_PROTOCOL_res
|
||||
{ &kNS_RESPROTOCOLHANDLER_CID, false, nullptr, nsResProtocolHandlerConstructor },
|
||||
{ &kNS_RESURL_CID, false, nullptr, nsResURLConstructor },
|
||||
{ &kNS_SUBSTITUTINGURL_CID, false, nullptr, mozilla::SubstitutingURLConstructor },
|
||||
#endif
|
||||
{ &kNS_ABOUTPROTOCOLHANDLER_CID, false, nullptr, nsAboutProtocolHandlerConstructor },
|
||||
{ &kNS_SAFEABOUTPROTOCOLHANDLER_CID, false, nullptr, nsSafeAboutProtocolHandlerConstructor },
|
||||
|
374
netwerk/protocol/res/SubstitutingProtocolHandler.cpp
Normal file
374
netwerk/protocol/res/SubstitutingProtocolHandler.cpp
Normal file
@ -0,0 +1,374 @@
|
||||
/* -*- 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 "mozilla/chrome/RegistryMessageUtils.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
#include "SubstitutingProtocolHandler.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsURLHelper.h"
|
||||
#include "nsEscape.h"
|
||||
|
||||
using mozilla::dom::ContentParent;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Log module for Substituting Protocol logging. We keep the pre-existing module
|
||||
// name of "nsResProtocol" to avoid disruption.
|
||||
static PRLogModuleInfo *gResLog;
|
||||
|
||||
static NS_DEFINE_CID(kSubstitutingURLCID, NS_SUBSTITUTINGURL_CID);
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// SubstitutingURL : overrides nsStandardURL::GetFile to provide nsIFile resolution
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
SubstitutingURL::EnsureFile()
|
||||
{
|
||||
nsAutoCString ourScheme;
|
||||
nsresult rv = GetScheme(ourScheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Get the handler associated with this scheme. It would be nice to just
|
||||
// pass this in when constructing SubstitutingURLs, but we need a generic
|
||||
// factory constructor.
|
||||
nsCOMPtr<nsIIOService> io = do_GetIOService(&rv);
|
||||
nsCOMPtr<nsIProtocolHandler> handler;
|
||||
rv = io->GetProtocolHandler(ourScheme.get(), getter_AddRefs(handler));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsISubstitutingProtocolHandler> substHandler = do_QueryInterface(handler);
|
||||
MOZ_ASSERT(substHandler);
|
||||
|
||||
nsAutoCString spec;
|
||||
rv = substHandler->ResolveURI(this, spec);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsAutoCString scheme;
|
||||
rv = net_ExtractURLScheme(spec, nullptr, nullptr, &scheme);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Bug 585869:
|
||||
// In most cases, the scheme is jar if it's not file.
|
||||
// Regardless, net_GetFileFromURLSpec should be avoided
|
||||
// when the scheme isn't file.
|
||||
if (!scheme.EqualsLiteral("file"))
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
|
||||
return net_GetFileFromURLSpec(spec, getter_AddRefs(mFile));
|
||||
}
|
||||
|
||||
/* virtual */ nsStandardURL*
|
||||
SubstitutingURL::StartClone()
|
||||
{
|
||||
SubstitutingURL *clone = new SubstitutingURL();
|
||||
return clone;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SubstitutingURL::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
|
||||
{
|
||||
*aClassIDNoAlloc = kSubstitutingURLCID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
SubstitutingProtocolHandler::SubstitutingProtocolHandler(const char* aScheme, uint32_t aFlags)
|
||||
: mScheme(aScheme)
|
||||
, mFlags(aFlags)
|
||||
, mSubstitutions(16)
|
||||
{
|
||||
nsresult rv;
|
||||
mIOService = do_GetIOService(&rv);
|
||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv) && mIOService);
|
||||
|
||||
if (!gResLog) {
|
||||
gResLog = PR_NewLogModule("nsResProtocol");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// IPC marshalling.
|
||||
//
|
||||
|
||||
struct EnumerateSubstitutionArg
|
||||
{
|
||||
EnumerateSubstitutionArg(nsCString& aScheme, nsTArray<SubstitutionMapping>& aMappings)
|
||||
: mScheme(aScheme), mMappings(aMappings) {}
|
||||
nsCString& mScheme;
|
||||
nsTArray<SubstitutionMapping>& mMappings;
|
||||
};
|
||||
|
||||
static PLDHashOperator
|
||||
EnumerateSubstitution(const nsACString& aKey,
|
||||
nsIURI* aURI,
|
||||
void* aArg)
|
||||
{
|
||||
auto arg = static_cast<EnumerateSubstitutionArg*>(aArg);
|
||||
SerializedURI uri;
|
||||
if (aURI) {
|
||||
aURI->GetSpec(uri.spec);
|
||||
aURI->GetOriginCharset(uri.charset);
|
||||
}
|
||||
|
||||
SubstitutionMapping substitution = { arg->mScheme, nsCString(aKey), uri };
|
||||
arg->mMappings.AppendElement(substitution);
|
||||
return (PLDHashOperator)PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
SubstitutingProtocolHandler::CollectSubstitutions(InfallibleTArray<SubstitutionMapping>& aMappings)
|
||||
{
|
||||
EnumerateSubstitutionArg arg(mScheme, aMappings);
|
||||
mSubstitutions.EnumerateRead(&EnumerateSubstitution, &arg);
|
||||
}
|
||||
|
||||
void
|
||||
SubstitutingProtocolHandler::SendSubstitution(const nsACString& aRoot, nsIURI* aBaseURI)
|
||||
{
|
||||
if (GeckoProcessType_Content == XRE_GetProcessType()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<ContentParent*> parents;
|
||||
ContentParent::GetAll(parents);
|
||||
if (!parents.Length()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SubstitutionMapping mapping;
|
||||
mapping.scheme = mScheme;
|
||||
mapping.path = aRoot;
|
||||
if (aBaseURI) {
|
||||
aBaseURI->GetSpec(mapping.resolvedURI.spec);
|
||||
aBaseURI->GetOriginCharset(mapping.resolvedURI.charset);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < parents.Length(); i++) {
|
||||
unused << parents[i]->SendRegisterChromeItem(mapping);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// nsIProtocolHandler
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
SubstitutingProtocolHandler::GetScheme(nsACString &result)
|
||||
{
|
||||
result = mScheme;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SubstitutingProtocolHandler::GetDefaultPort(int32_t *result)
|
||||
{
|
||||
*result = -1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SubstitutingProtocolHandler::GetProtocolFlags(uint32_t *result)
|
||||
{
|
||||
*result = mFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SubstitutingProtocolHandler::NewURI(const nsACString &aSpec,
|
||||
const char *aCharset,
|
||||
nsIURI *aBaseURI,
|
||||
nsIURI **result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsRefPtr<SubstitutingURL> url = new SubstitutingURL();
|
||||
if (!url)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// unescape any %2f and %2e to make sure nsStandardURL coalesces them.
|
||||
// Later net_GetFileFromURLSpec() will do a full unescape and we want to
|
||||
// treat them the same way the file system will. (bugs 380994, 394075)
|
||||
nsAutoCString spec;
|
||||
const char *src = aSpec.BeginReading();
|
||||
const char *end = aSpec.EndReading();
|
||||
const char *last = src;
|
||||
|
||||
spec.SetCapacity(aSpec.Length()+1);
|
||||
for ( ; src < end; ++src) {
|
||||
if (*src == '%' && (src < end-2) && *(src+1) == '2') {
|
||||
char ch = '\0';
|
||||
if (*(src+2) == 'f' || *(src+2) == 'F') {
|
||||
ch = '/';
|
||||
} else if (*(src+2) == 'e' || *(src+2) == 'E') {
|
||||
ch = '.';
|
||||
}
|
||||
|
||||
if (ch) {
|
||||
if (last < src) {
|
||||
spec.Append(last, src-last);
|
||||
}
|
||||
spec.Append(ch);
|
||||
src += 2;
|
||||
last = src+1; // src will be incremented by the loop
|
||||
}
|
||||
}
|
||||
}
|
||||
if (last < src)
|
||||
spec.Append(last, src-last);
|
||||
|
||||
rv = url->Init(nsIStandardURL::URLTYPE_STANDARD, -1, spec, aCharset, aBaseURI);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
url.forget(result);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SubstitutingProtocolHandler::NewChannel2(nsIURI* uri,
|
||||
nsILoadInfo* aLoadInfo,
|
||||
nsIChannel** result)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(uri);
|
||||
nsAutoCString spec;
|
||||
nsresult rv = ResolveURI(uri, spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
rv = NS_NewURI(getter_AddRefs(newURI), spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = NS_NewChannelInternal(result, newURI, aLoadInfo);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsLoadFlags loadFlags = 0;
|
||||
(*result)->GetLoadFlags(&loadFlags);
|
||||
(*result)->SetLoadFlags(loadFlags & ~nsIChannel::LOAD_REPLACE);
|
||||
return (*result)->SetOriginalURI(uri);
|
||||
}
|
||||
|
||||
nsresult
|
||||
SubstitutingProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
||||
{
|
||||
return NewChannel2(uri, nullptr, result);
|
||||
}
|
||||
|
||||
nsresult
|
||||
SubstitutingProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
|
||||
{
|
||||
// don't override anything.
|
||||
*_retval = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// nsISubstitutingProtocolHandler
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
SubstitutingProtocolHandler::SetSubstitution(const nsACString& root, nsIURI *baseURI)
|
||||
{
|
||||
if (!baseURI) {
|
||||
mSubstitutions.Remove(root);
|
||||
SendSubstitution(root, baseURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If baseURI isn't a same-scheme URI, we can set the substitution immediately.
|
||||
nsAutoCString scheme;
|
||||
nsresult rv = baseURI->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!scheme.Equals(mScheme)) {
|
||||
mSubstitutions.Put(root, baseURI);
|
||||
SendSubstitution(root, baseURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// baseURI is a same-type substituting URI, let's resolve it first.
|
||||
nsAutoCString newBase;
|
||||
rv = ResolveURI(baseURI, newBase);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> newBaseURI;
|
||||
rv = mIOService->NewURI(newBase, nullptr, nullptr, getter_AddRefs(newBaseURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mSubstitutions.Put(root, newBaseURI);
|
||||
SendSubstitution(root, newBaseURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SubstitutingProtocolHandler::GetSubstitution(const nsACString& root, nsIURI **result)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(result);
|
||||
|
||||
if (mSubstitutions.Get(root, result))
|
||||
return NS_OK;
|
||||
|
||||
return GetSubstitutionInternal(root, result);
|
||||
}
|
||||
|
||||
nsresult
|
||||
SubstitutingProtocolHandler::HasSubstitution(const nsACString& root, bool *result)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(result);
|
||||
|
||||
*result = mSubstitutions.Get(root, nullptr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SubstitutingProtocolHandler::ResolveURI(nsIURI *uri, nsACString &result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString host;
|
||||
nsAutoCString path;
|
||||
|
||||
rv = uri->GetAsciiHost(host);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = uri->GetPath(path);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Unescape the path so we can perform some checks on it.
|
||||
nsAutoCString unescapedPath(path);
|
||||
NS_UnescapeURL(unescapedPath);
|
||||
|
||||
// Don't misinterpret the filepath as an absolute URI.
|
||||
if (unescapedPath.FindChar(':') != -1)
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
|
||||
if (unescapedPath.FindChar('\\') != -1)
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
|
||||
const char *p = path.get() + 1; // path always starts with a slash
|
||||
NS_ASSERTION(*(p-1) == '/', "Path did not begin with a slash!");
|
||||
|
||||
if (*p == '/')
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
rv = GetSubstitution(host, getter_AddRefs(baseURI));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = baseURI->Resolve(nsDependentCString(p, path.Length()-1), result);
|
||||
|
||||
if (MOZ_LOG_TEST(gResLog, LogLevel::Debug)) {
|
||||
nsAutoCString spec;
|
||||
uri->GetAsciiSpec(spec);
|
||||
MOZ_LOG(gResLog, LogLevel::Debug, ("%s\n -> %s\n", spec.get(), PromiseFlatCString(result).get()));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
71
netwerk/protocol/res/SubstitutingProtocolHandler.h
Normal file
71
netwerk/protocol/res/SubstitutingProtocolHandler.h
Normal file
@ -0,0 +1,71 @@
|
||||
/* -*- 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 SubstitutingProtocolHandler_h___
|
||||
#define SubstitutingProtocolHandler_h___
|
||||
|
||||
#include "nsISubstitutingProtocolHandler.h"
|
||||
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsIOService.h"
|
||||
#include "nsStandardURL.h"
|
||||
#include "mozilla/chrome/RegistryMessageUtils.h"
|
||||
|
||||
class nsIIOService;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
//
|
||||
// Base class for resource://-like substitution protocols.
|
||||
//
|
||||
// If you add a new protocol, make sure to change nsChromeRegistryChrome
|
||||
// to properly invoke CollectSubstitutions at the right time.
|
||||
class SubstitutingProtocolHandler
|
||||
{
|
||||
public:
|
||||
SubstitutingProtocolHandler(const char* aScheme, uint32_t aFlags);
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(SubstitutingProtocolHandler);
|
||||
NS_DECL_NON_VIRTUAL_NSIPROTOCOLHANDLER;
|
||||
NS_DECL_NON_VIRTUAL_NSISUBSTITUTINGPROTOCOLHANDLER;
|
||||
|
||||
void CollectSubstitutions(InfallibleTArray<SubstitutionMapping>& aResources);
|
||||
|
||||
protected:
|
||||
virtual ~SubstitutingProtocolHandler() {}
|
||||
|
||||
void SendSubstitution(const nsACString& aRoot, nsIURI* aBaseURI);
|
||||
|
||||
// Override this in the subclass to try additional lookups after checking
|
||||
// mSubstitutions.
|
||||
virtual nsresult GetSubstitutionInternal(const nsACString& aRoot, nsIURI** aResult)
|
||||
{
|
||||
*aResult = nullptr;
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsIIOService* IOService() { return mIOService; }
|
||||
|
||||
private:
|
||||
nsCString mScheme;
|
||||
uint32_t mFlags;
|
||||
nsInterfaceHashtable<nsCStringHashKey,nsIURI> mSubstitutions;
|
||||
nsCOMPtr<nsIIOService> mIOService;
|
||||
};
|
||||
|
||||
// SubstitutingURL : overrides nsStandardURL::GetFile to provide nsIFile resolution
|
||||
class SubstitutingURL : public nsStandardURL
|
||||
{
|
||||
public:
|
||||
SubstitutingURL() : nsStandardURL(true) {}
|
||||
virtual nsStandardURL* StartClone();
|
||||
virtual nsresult EnsureFile();
|
||||
NS_IMETHOD GetClassIDNoAlloc(nsCID *aCID);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* SubstitutingProtocolHandler_h___ */
|
@ -6,12 +6,14 @@
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIResProtocolHandler.idl',
|
||||
'nsISubstitutingProtocolHandler.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'necko_res'
|
||||
|
||||
SOURCES += [
|
||||
'nsResProtocolHandler.cpp',
|
||||
'SubstitutingProtocolHandler.cpp',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
@ -3,43 +3,12 @@
|
||||
* 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 "nsIProtocolHandler.idl"
|
||||
#include "nsISubstitutingProtocolHandler.idl"
|
||||
|
||||
/**
|
||||
* Protocol handler interface for the resource:// protocol
|
||||
*/
|
||||
[scriptable, uuid(067ca872-e947-4bd6-8946-a479cb6ba5dd)]
|
||||
interface nsIResProtocolHandler : nsIProtocolHandler
|
||||
[scriptable, uuid(241d34ac-9ed5-46d7-910c-7a9d914aa0c5)]
|
||||
interface nsIResProtocolHandler : nsISubstitutingProtocolHandler
|
||||
{
|
||||
/**
|
||||
* Sets the substitution for the root key:
|
||||
* resource://root/path ==> baseURI.resolve(path)
|
||||
*
|
||||
* A null baseURI removes the specified substitution.
|
||||
*
|
||||
* A root key should always be lowercase; however, this may not be
|
||||
* enforced.
|
||||
*/
|
||||
void setSubstitution(in ACString root, in nsIURI baseURI);
|
||||
|
||||
/**
|
||||
* Gets the substitution for the root key.
|
||||
*
|
||||
* @throws NS_ERROR_NOT_AVAILABLE if none exists.
|
||||
*/
|
||||
nsIURI getSubstitution(in ACString root);
|
||||
|
||||
/**
|
||||
* Returns TRUE if the substitution exists and FALSE otherwise.
|
||||
*/
|
||||
boolean hasSubstitution(in ACString root);
|
||||
|
||||
/**
|
||||
* Utility function to resolve a resource URI. A resolved URI is not
|
||||
* guaranteed to reference a resource that exists (ie. opening a channel to
|
||||
* the resolved URI may fail).
|
||||
*
|
||||
* @throws NS_ERROR_NOT_AVAILABLE if resURI.host() is an unknown root key.
|
||||
*/
|
||||
AUTF8String resolveURI(in nsIURI resURI);
|
||||
};
|
||||
|
46
netwerk/protocol/res/nsISubstitutingProtocolHandler.idl
Normal file
46
netwerk/protocol/res/nsISubstitutingProtocolHandler.idl
Normal file
@ -0,0 +1,46 @@
|
||||
/* -*- Mode: C++; tab-width: 2; 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 "nsIProtocolHandler.idl"
|
||||
|
||||
/**
|
||||
* Protocol handler superinterface for a protocol which performs substitutions
|
||||
* from URIs of its scheme to URIs of another scheme.
|
||||
*/
|
||||
[scriptable, uuid(154c64fd-a69e-4105-89f8-bd7dfe621372)]
|
||||
interface nsISubstitutingProtocolHandler : nsIProtocolHandler
|
||||
{
|
||||
/**
|
||||
* Sets the substitution for the root key:
|
||||
* resource://root/path ==> baseURI.resolve(path)
|
||||
*
|
||||
* A null baseURI removes the specified substitution.
|
||||
*
|
||||
* A root key should always be lowercase; however, this may not be
|
||||
* enforced.
|
||||
*/
|
||||
void setSubstitution(in ACString root, in nsIURI baseURI);
|
||||
|
||||
/**
|
||||
* Gets the substitution for the root key.
|
||||
*
|
||||
* @throws NS_ERROR_NOT_AVAILABLE if none exists.
|
||||
*/
|
||||
nsIURI getSubstitution(in ACString root);
|
||||
|
||||
/**
|
||||
* Returns TRUE if the substitution exists and FALSE otherwise.
|
||||
*/
|
||||
boolean hasSubstitution(in ACString root);
|
||||
|
||||
/**
|
||||
* Utility function to resolve a substituted URI. A resolved URI is not
|
||||
* guaranteed to reference a resource that exists (ie. opening a channel to
|
||||
* the resolved URI may fail).
|
||||
*
|
||||
* @throws NS_ERROR_NOT_AVAILABLE if resURI.host() is an unknown root key.
|
||||
*/
|
||||
AUTF8String resolveURI(in nsIURI resURI);
|
||||
};
|
@ -21,108 +21,13 @@ using mozilla::dom::ContentParent;
|
||||
using mozilla::LogLevel;
|
||||
using mozilla::unused;
|
||||
|
||||
static NS_DEFINE_CID(kResURLCID, NS_RESURL_CID);
|
||||
|
||||
static nsResProtocolHandler *gResHandler = nullptr;
|
||||
|
||||
//
|
||||
// Log module for Resource Protocol logging...
|
||||
//
|
||||
// To enable logging (see prlog.h for full details):
|
||||
//
|
||||
// set NSPR_LOG_MODULES=nsResProtocol:5
|
||||
// set NSPR_LOG_FILE=log.txt
|
||||
//
|
||||
// this enables LogLevel::Debug level information and places all output in
|
||||
// the file log.txt
|
||||
//
|
||||
static PRLogModuleInfo *gResLog;
|
||||
|
||||
#define kAPP NS_LITERAL_CSTRING("app")
|
||||
#define kGRE NS_LITERAL_CSTRING("gre")
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// nsResURL : overrides nsStandardURL::GetFile to provide nsIFile resolution
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
nsResURL::EnsureFile()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
NS_ENSURE_TRUE(gResHandler, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsAutoCString spec;
|
||||
rv = gResHandler->ResolveURI(this, spec);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsAutoCString scheme;
|
||||
rv = net_ExtractURLScheme(spec, nullptr, nullptr, &scheme);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Bug 585869:
|
||||
// In most cases, the scheme is jar if it's not file.
|
||||
// Regardless, net_GetFileFromURLSpec should be avoided
|
||||
// when the scheme isn't file.
|
||||
if (!scheme.EqualsLiteral("file"))
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
|
||||
rv = net_GetFileFromURLSpec(spec, getter_AddRefs(mFile));
|
||||
#ifdef DEBUG_bsmedberg
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
bool exists = true;
|
||||
mFile->Exists(&exists);
|
||||
if (!exists) {
|
||||
printf("resource %s doesn't exist!\n", spec.get());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* virtual */ nsStandardURL*
|
||||
nsResURL::StartClone()
|
||||
{
|
||||
nsResURL *clone = new nsResURL();
|
||||
return clone;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResURL::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
|
||||
{
|
||||
*aClassIDNoAlloc = kResURLCID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// nsResProtocolHandler <public>
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
nsResProtocolHandler::nsResProtocolHandler()
|
||||
: mSubstitutions(16)
|
||||
{
|
||||
gResLog = PR_NewLogModule("nsResProtocol");
|
||||
|
||||
NS_ASSERTION(!gResHandler, "res handler already created!");
|
||||
gResHandler = this;
|
||||
}
|
||||
|
||||
nsResProtocolHandler::~nsResProtocolHandler()
|
||||
{
|
||||
gResHandler = nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsResProtocolHandler::Init()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mIOService = do_GetIOService(&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString appURI, greURI;
|
||||
rv = mozilla::Omnijar::GetURIString(mozilla::Omnijar::APP, appURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -165,226 +70,19 @@ nsResProtocolHandler::Init()
|
||||
return rv;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
EnumerateSubstitution(const nsACString& aKey,
|
||||
nsIURI* aURI,
|
||||
void* aArg)
|
||||
{
|
||||
nsTArray<ResourceMapping>* resources =
|
||||
static_cast<nsTArray<ResourceMapping>*>(aArg);
|
||||
SerializedURI uri;
|
||||
if (aURI) {
|
||||
aURI->GetSpec(uri.spec);
|
||||
aURI->GetOriginCharset(uri.charset);
|
||||
}
|
||||
|
||||
ResourceMapping resource = {
|
||||
nsCString(aKey), uri
|
||||
};
|
||||
resources->AppendElement(resource);
|
||||
return (PLDHashOperator)PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsResProtocolHandler::CollectSubstitutions(InfallibleTArray<ResourceMapping>& aResources)
|
||||
{
|
||||
mSubstitutions.EnumerateRead(&EnumerateSubstitution, &aResources);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// nsResProtocolHandler::nsISupports
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsResProtocolHandler,
|
||||
nsIResProtocolHandler,
|
||||
nsIProtocolHandler,
|
||||
nsISupportsWeakReference)
|
||||
NS_IMPL_QUERY_INTERFACE(nsResProtocolHandler, nsIResProtocolHandler,
|
||||
nsISubstitutingProtocolHandler, nsIProtocolHandler,
|
||||
nsISupportsWeakReference)
|
||||
NS_IMPL_ADDREF_INHERITED(nsResProtocolHandler, SubstitutingProtocolHandler)
|
||||
NS_IMPL_RELEASE_INHERITED(nsResProtocolHandler, SubstitutingProtocolHandler)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// nsResProtocolHandler::nsIProtocolHandler
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::GetScheme(nsACString &result)
|
||||
nsresult
|
||||
nsResProtocolHandler::GetSubstitutionInternal(const nsACString& root, nsIURI **result)
|
||||
{
|
||||
result.AssignLiteral("resource");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::GetDefaultPort(int32_t *result)
|
||||
{
|
||||
*result = -1; // no port for res: URLs
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::GetProtocolFlags(uint32_t *result)
|
||||
{
|
||||
// XXXbz Is this really true for all resource: URIs? Could we
|
||||
// somehow give different flags to some of them?
|
||||
*result = URI_STD | URI_IS_UI_RESOURCE | URI_IS_LOCAL_RESOURCE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::NewURI(const nsACString &aSpec,
|
||||
const char *aCharset,
|
||||
nsIURI *aBaseURI,
|
||||
nsIURI **result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsRefPtr<nsResURL> resURL = new nsResURL();
|
||||
if (!resURL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// unescape any %2f and %2e to make sure nsStandardURL coalesces them.
|
||||
// Later net_GetFileFromURLSpec() will do a full unescape and we want to
|
||||
// treat them the same way the file system will. (bugs 380994, 394075)
|
||||
nsAutoCString spec;
|
||||
const char *src = aSpec.BeginReading();
|
||||
const char *end = aSpec.EndReading();
|
||||
const char *last = src;
|
||||
|
||||
spec.SetCapacity(aSpec.Length()+1);
|
||||
for ( ; src < end; ++src) {
|
||||
if (*src == '%' && (src < end-2) && *(src+1) == '2') {
|
||||
char ch = '\0';
|
||||
if (*(src+2) == 'f' || *(src+2) == 'F')
|
||||
ch = '/';
|
||||
else if (*(src+2) == 'e' || *(src+2) == 'E')
|
||||
ch = '.';
|
||||
|
||||
if (ch) {
|
||||
if (last < src)
|
||||
spec.Append(last, src-last);
|
||||
spec.Append(ch);
|
||||
src += 2;
|
||||
last = src+1; // src will be incremented by the loop
|
||||
}
|
||||
}
|
||||
}
|
||||
if (last < src)
|
||||
spec.Append(last, src-last);
|
||||
|
||||
rv = resURL->Init(nsIStandardURL::URLTYPE_STANDARD, -1, spec, aCharset, aBaseURI);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
resURL.forget(result);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::NewChannel2(nsIURI* uri,
|
||||
nsILoadInfo* aLoadInfo,
|
||||
nsIChannel** result)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(uri);
|
||||
nsAutoCString spec;
|
||||
nsresult rv = ResolveURI(uri, spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
rv = NS_NewURI(getter_AddRefs(newURI), spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = NS_NewChannelInternal(result,
|
||||
newURI,
|
||||
aLoadInfo);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsLoadFlags loadFlags = 0;
|
||||
(*result)->GetLoadFlags(&loadFlags);
|
||||
(*result)->SetLoadFlags(loadFlags & ~nsIChannel::LOAD_REPLACE);
|
||||
return (*result)->SetOriginalURI(uri);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
||||
{
|
||||
return NewChannel2(uri, nullptr, result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
|
||||
{
|
||||
// don't override anything.
|
||||
*_retval = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// nsResProtocolHandler::nsIResProtocolHandler
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static void
|
||||
SendResourceSubstitution(const nsACString& root, nsIURI* baseURI)
|
||||
{
|
||||
if (GeckoProcessType_Content == XRE_GetProcessType()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ResourceMapping resourceMapping;
|
||||
resourceMapping.resource = root;
|
||||
if (baseURI) {
|
||||
baseURI->GetSpec(resourceMapping.resolvedURI.spec);
|
||||
baseURI->GetOriginCharset(resourceMapping.resolvedURI.charset);
|
||||
}
|
||||
|
||||
nsTArray<ContentParent*> parents;
|
||||
ContentParent::GetAll(parents);
|
||||
if (!parents.Length()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < parents.Length(); i++) {
|
||||
unused << parents[i]->SendRegisterChromeItem(resourceMapping);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::SetSubstitution(const nsACString& root, nsIURI *baseURI)
|
||||
{
|
||||
if (!baseURI) {
|
||||
mSubstitutions.Remove(root);
|
||||
SendResourceSubstitution(root, baseURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If baseURI isn't a resource URI, we can set the substitution immediately.
|
||||
nsAutoCString scheme;
|
||||
nsresult rv = baseURI->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!scheme.EqualsLiteral("resource")) {
|
||||
mSubstitutions.Put(root, baseURI);
|
||||
SendResourceSubstitution(root, baseURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// baseURI is a resource URI, let's resolve it first.
|
||||
nsAutoCString newBase;
|
||||
rv = ResolveURI(baseURI, newBase);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> newBaseURI;
|
||||
rv = mIOService->NewURI(newBase, nullptr, nullptr,
|
||||
getter_AddRefs(newBaseURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mSubstitutions.Put(root, newBaseURI);
|
||||
SendResourceSubstitution(root, newBaseURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::GetSubstitution(const nsACString& root, nsIURI **result)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(result);
|
||||
|
||||
if (mSubstitutions.Get(root, result))
|
||||
return NS_OK;
|
||||
|
||||
// try invoking the directory service for "resource:root"
|
||||
|
||||
nsAutoCString key;
|
||||
@ -396,64 +94,9 @@ nsResProtocolHandler::GetSubstitution(const nsACString& root, nsIURI **result)
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
rv = mIOService->NewFileURI(file, result);
|
||||
rv = IOService()->NewFileURI(file, result);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::HasSubstitution(const nsACString& root, bool *result)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(result);
|
||||
|
||||
*result = mSubstitutions.Get(root, nullptr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::ResolveURI(nsIURI *uri, nsACString &result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString host;
|
||||
nsAutoCString path;
|
||||
|
||||
rv = uri->GetAsciiHost(host);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = uri->GetPath(path);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Unescape the path so we can perform some checks on it.
|
||||
nsAutoCString unescapedPath(path);
|
||||
NS_UnescapeURL(unescapedPath);
|
||||
|
||||
// Don't misinterpret the filepath as an absolute URI.
|
||||
if (unescapedPath.FindChar(':') != -1)
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
|
||||
if (unescapedPath.FindChar('\\') != -1)
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
|
||||
const char *p = path.get() + 1; // path always starts with a slash
|
||||
NS_ASSERTION(*(p-1) == '/', "Path did not begin with a slash!");
|
||||
|
||||
if (*p == '/')
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
rv = GetSubstitution(host, getter_AddRefs(baseURI));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = baseURI->Resolve(nsDependentCString(p, path.Length()-1), result);
|
||||
|
||||
if (MOZ_LOG_TEST(gResLog, LogLevel::Debug)) {
|
||||
nsAutoCString spec;
|
||||
uri->GetAsciiSpec(spec);
|
||||
MOZ_LOG(gResLog, LogLevel::Debug,
|
||||
("%s\n -> %s\n", spec.get(), PromiseFlatCString(result).get()));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -6,46 +6,34 @@
|
||||
#ifndef nsResProtocolHandler_h___
|
||||
#define nsResProtocolHandler_h___
|
||||
|
||||
#include "SubstitutingProtocolHandler.h"
|
||||
|
||||
#include "nsIResProtocolHandler.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsStandardURL.h"
|
||||
|
||||
class nsIIOService;
|
||||
struct ResourceMapping;
|
||||
|
||||
// nsResURL : overrides nsStandardURL::GetFile to provide nsIFile resolution
|
||||
class nsResURL : public nsStandardURL
|
||||
struct SubstitutionMapping;
|
||||
class nsResProtocolHandler final : public nsIResProtocolHandler,
|
||||
public mozilla::SubstitutingProtocolHandler,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
nsResURL() : nsStandardURL(true) {}
|
||||
virtual nsStandardURL* StartClone();
|
||||
virtual nsresult EnsureFile();
|
||||
NS_IMETHOD GetClassIDNoAlloc(nsCID *aCID);
|
||||
};
|
||||
|
||||
class nsResProtocolHandler final : public nsIResProtocolHandler, public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPROTOCOLHANDLER
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIRESPROTOCOLHANDLER
|
||||
|
||||
nsResProtocolHandler();
|
||||
NS_FORWARD_NSIPROTOCOLHANDLER(mozilla::SubstitutingProtocolHandler::)
|
||||
NS_FORWARD_NSISUBSTITUTINGPROTOCOLHANDLER(mozilla::SubstitutingProtocolHandler::)
|
||||
|
||||
nsResProtocolHandler()
|
||||
: SubstitutingProtocolHandler("resource", URI_STD | URI_IS_UI_RESOURCE | URI_IS_LOCAL_RESOURCE)
|
||||
{}
|
||||
|
||||
nsresult Init();
|
||||
|
||||
void CollectSubstitutions(InfallibleTArray<ResourceMapping>& aResources);
|
||||
|
||||
private:
|
||||
virtual ~nsResProtocolHandler();
|
||||
|
||||
nsresult Init(nsIFile *aOmniJar);
|
||||
nsresult AddSpecialDir(const char* aSpecialDir, const nsACString& aSubstitution);
|
||||
nsInterfaceHashtable<nsCStringHashKey,nsIURI> mSubstitutions;
|
||||
nsCOMPtr<nsIIOService> mIOService;
|
||||
|
||||
friend class nsResURL;
|
||||
protected:
|
||||
nsresult GetSubstitutionInternal(const nsACString& aRoot, nsIURI** aResult) override;
|
||||
virtual ~nsResProtocolHandler() {}
|
||||
};
|
||||
|
||||
#endif /* nsResProtocolHandler_h___ */
|
||||
|
Loading…
Reference in New Issue
Block a user