Chrome protocol handler should not munge URIs on channel open (and remove some

workarounds around that behavior).  Bug 182124, r=rjc, sr=darin
This commit is contained in:
bzbarsky%mit.edu 2002-12-11 03:29:27 +00:00
parent f1ebcab55a
commit f3c5ef51ac
7 changed files with 207 additions and 76 deletions

View File

@ -77,6 +77,9 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
static NS_DEFINE_CID(kXULPrototypeCacheCID, NS_XULPROTOTYPECACHE_CID);
// This comes from nsChromeRegistry.cpp
extern nsIChromeRegistry* gChromeRegistry;
//----------------------------------------------------------------------
//
// A channel that's used for loading cached chrome documents. Since a
@ -566,8 +569,12 @@ nsChromeProtocolHandler::NewURI(const nsACString &aSpec,
nsIURI *aBaseURI,
nsIURI **result)
{
NS_PRECONDITION(result, "Null out param");
nsresult rv;
*result = nsnull;
// Chrome: URLs (currently) have no additional structure beyond that provided
// by standard URLs, so there is no "outer" given to CreateInstance
@ -579,25 +586,67 @@ nsChromeProtocolHandler::NewURI(const nsACString &aSpec,
if (NS_FAILED(rv))
return rv;
return CallQueryInterface(url, result);
nsCOMPtr<nsIURI> uri(do_QueryInterface(url, &rv));
if (NS_FAILED(rv))
return rv;
// Canonify the "chrome:" URL; e.g., so that we collapse
// "chrome://navigator/content/" and "chrome://navigator/content"
// and "chrome://navigator/content/navigator.xul".
// Try the global cache first.
nsCOMPtr<nsIChromeRegistry> reg = gChromeRegistry;
// If that fails, the service has not been instantiated it; let's
// do that now.
if (!reg) {
reg = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
}
NS_ASSERTION(reg, "Must have a chrome registry by now");
rv = reg->Canonify(uri);
if (NS_FAILED(rv))
return rv;
*result = uri;
NS_ADDREF(*result);
return NS_OK;
}
NS_IMETHODIMP
nsChromeProtocolHandler::NewChannel(nsIURI* aURI,
nsIChannel* *aResult)
{
NS_ENSURE_ARG_POINTER(aURI);
NS_PRECONDITION(aResult, "Null out param");
#ifdef DEBUG
// Check that the uri we got is already canonified
nsresult debug_rv;
nsCOMPtr<nsIChromeRegistry> debugReg(do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &debug_rv));
if (NS_SUCCEEDED(debug_rv)) {
nsCOMPtr<nsIURI> debugClone;
debug_rv = aURI->Clone(getter_AddRefs(debugClone));
if (NS_SUCCEEDED(debug_rv)) {
debug_rv = debugReg->Canonify(debugClone);
if (NS_SUCCEEDED(debug_rv)) {
PRBool same;
debug_rv = aURI->Equals(debugClone, &same);
if (NS_SUCCEEDED(debug_rv)) {
NS_ASSERTION(same, "Non-canonified chrome uri passed to nsChromeProtocolHandler::NewChannel!");
}
}
}
}
#endif
nsresult rv;
nsCOMPtr<nsIChannel> result;
// Canonify the "chrome:" URL; e.g., so that we collapse
// "chrome://navigator/content/navigator.xul" and "chrome://navigator/content"
// and "chrome://navigator/content/navigator.xul".
nsCOMPtr<nsIChromeRegistry> reg(do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv));
if (NS_FAILED(rv)) return rv;
rv = reg->Canonify(aURI);
if (NS_FAILED(rv)) return rv;
// Check the prototype cache to see if we've already got the
// document in the cache.
nsCOMPtr<nsIXULPrototypeCache> cache =
@ -636,6 +685,12 @@ nsChromeProtocolHandler::NewChannel(nsIURI* aURI,
//aURI->GetSpec(getter_Copies(oldSpec));
//printf("*************************** %s\n", (const char*)oldSpec);
nsCOMPtr<nsIChromeRegistry> reg = gChromeRegistry;
if (!reg) {
reg = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
}
nsCAutoString spec;
rv = reg->ConvertChromeURL(aURI, spec);
if (NS_FAILED(rv)) return rv;

View File

@ -128,6 +128,8 @@ static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
class nsChromeRegistry;
nsIChromeRegistry* gChromeRegistry = nsnull;
#define CHROME_URI "http://www.mozilla.org/rdf/chrome#"
DEFINE_RDF_VOCAB(CHROME_URI, CHROME, selectedSkin);
@ -288,6 +290,8 @@ static PRBool PR_CALLBACK DatasourceEnumerator(nsHashKey *aKey, void *aData, voi
nsChromeRegistry::~nsChromeRegistry()
{
gChromeRegistry = nsnull;
if (mDataSourceTable) {
mDataSourceTable->Enumerate(DatasourceEnumerator, mChromeDataSource);
delete mDataSourceTable;
@ -313,6 +317,8 @@ NS_IMPL_THREADSAFE_ISUPPORTS4(nsChromeRegistry, nsIChromeRegistry, nsIXULChromeR
nsresult
nsChromeRegistry::Init()
{
gChromeRegistry = this;
nsresult rv;
rv = nsServiceManager::GetService(kRDFServiceCID,
NS_GET_IID(nsIRDFService),

View File

@ -1516,18 +1516,6 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
return NS_OK;
}
// We have to clone the URI because we're using it as the hash key and necko
// will munge it. For example, "chrome://communicator/skin/" will become
// "chrome://communicator/skin/communicator.css" if you open a channel with
// it.. :(
nsCOMPtr<nsIURI> uriClone;
rv = aLoadData->mURI->Clone(getter_AddRefs(uriClone));
if (!uriClone) {
LOG_ERROR((" Failed to clone URI"));
SheetComplete(aLoadData, PR_FALSE);
return rv;
}
if (aLoadData->mSyncLoad) {
LOG((" Synchronous load"));
NS_ASSERTION(aSheetState == eSheetNeedsParser,
@ -1535,7 +1523,7 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
// Just load it
nsCOMPtr<nsIInputStream> stream;
rv = NS_OpenURI(getter_AddRefs(stream), uriClone);
rv = NS_OpenURI(getter_AddRefs(stream), aLoadData->mURI);
if (NS_FAILED(rv)) {
LOG_ERROR((" Failed to open URI synchronously"));
SheetComplete(aLoadData, PR_FALSE);
@ -1617,13 +1605,13 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
}
#ifdef MOZ_TIMELINE
NS_TIMELINE_MARK_URI("Loading style sheet: %s", uriClone);
NS_TIMELINE_MARK_URI("Loading style sheet: %s", aLoadData->mURI);
NS_TIMELINE_INDENT();
#endif
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel),
uriClone, nsnull, loadGroup,
aLoadData->mURI, nsnull, loadGroup,
nsnull, nsIChannel::LOAD_NORMAL);
if (NS_FAILED(rv)) {

View File

@ -1516,18 +1516,6 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
return NS_OK;
}
// We have to clone the URI because we're using it as the hash key and necko
// will munge it. For example, "chrome://communicator/skin/" will become
// "chrome://communicator/skin/communicator.css" if you open a channel with
// it.. :(
nsCOMPtr<nsIURI> uriClone;
rv = aLoadData->mURI->Clone(getter_AddRefs(uriClone));
if (!uriClone) {
LOG_ERROR((" Failed to clone URI"));
SheetComplete(aLoadData, PR_FALSE);
return rv;
}
if (aLoadData->mSyncLoad) {
LOG((" Synchronous load"));
NS_ASSERTION(aSheetState == eSheetNeedsParser,
@ -1535,7 +1523,7 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
// Just load it
nsCOMPtr<nsIInputStream> stream;
rv = NS_OpenURI(getter_AddRefs(stream), uriClone);
rv = NS_OpenURI(getter_AddRefs(stream), aLoadData->mURI);
if (NS_FAILED(rv)) {
LOG_ERROR((" Failed to open URI synchronously"));
SheetComplete(aLoadData, PR_FALSE);
@ -1617,13 +1605,13 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
}
#ifdef MOZ_TIMELINE
NS_TIMELINE_MARK_URI("Loading style sheet: %s", uriClone);
NS_TIMELINE_MARK_URI("Loading style sheet: %s", aLoadData->mURI);
NS_TIMELINE_INDENT();
#endif
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel),
uriClone, nsnull, loadGroup,
aLoadData->mURI, nsnull, loadGroup,
nsnull, nsIChannel::LOAD_NORMAL);
if (NS_FAILED(rv)) {

View File

@ -231,7 +231,6 @@ protected:
nsVoidArray mObservers; // OWNER
nsCOMPtr<nsIURI> mURL;
nsCOMPtr<nsIStreamListener> mListener;
nsXPIDLCString mOriginalURLSpec;
nsNameSpaceMap mNameSpaces;
// pseudo-constants
@ -637,14 +636,10 @@ RDFXMLDataSourceImpl::Init(const char* uri)
rv = NS_NewURI(getter_AddRefs(mURL), nsDependentCString(uri));
if (NS_FAILED(rv)) return rv;
// Keep a 'cached' copy of the URL; opening it may cause the spec
// to be re-written.
mURL->GetSpec(mOriginalURLSpec);
// XXX this is a hack: any "file:" URI is considered writable. All
// others are considered read-only.
if ((PL_strncmp(mOriginalURLSpec, kFileURIPrefix, sizeof(kFileURIPrefix) - 1) != 0) &&
(PL_strncmp(mOriginalURLSpec, kResourceURIPrefix, sizeof(kResourceURIPrefix) - 1) != 0)) {
if ((PL_strncmp(uri, kFileURIPrefix, sizeof(kFileURIPrefix) - 1) != 0) &&
(PL_strncmp(uri, kResourceURIPrefix, sizeof(kResourceURIPrefix) - 1) != 0)) {
mIsWritable = PR_FALSE;
}
@ -659,13 +654,17 @@ NS_IMETHODIMP
RDFXMLDataSourceImpl::GetURI(char* *aURI)
{
*aURI = nsnull;
if (mOriginalURLSpec) {
// We don't use the mURL, because it might get re-written when
// it's actually opened.
*aURI = nsCRT::strdup(mOriginalURLSpec);
if (! *aURI)
return NS_ERROR_OUT_OF_MEMORY;
if (!mURL) {
return NS_OK;
}
nsCAutoString spec;
mURL->GetSpec(spec);
*aURI = ToNewCString(spec);
if (!*aURI) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
@ -861,11 +860,15 @@ RDFXMLDataSourceImpl::Flush(void)
// while it is not fatal if mOriginalURLSpec is not set,
// indicate failure since we can't flush back to an unknown origin
if (! mOriginalURLSpec)
if (! mURL)
return NS_ERROR_NOT_INITIALIZED;
#ifdef PR_LOGGING
nsCAutoString spec;
mURL->GetSpec(spec);
PR_LOG(gLog, PR_LOG_ALWAYS,
("rdfxml[%p] flush(%s)", this, mOriginalURLSpec.get()));
("rdfxml[%p] flush(%s)", this, spec.get()));
#endif
nsresult rv;
if (NS_SUCCEEDED(rv = rdfXMLFlush(mURL)))
@ -903,14 +906,20 @@ RDFXMLDataSourceImpl::SetReadOnly(PRBool aIsReadOnly)
NS_IMETHODIMP
RDFXMLDataSourceImpl::Refresh(PRBool aBlocking)
{
#ifdef PR_LOGGING
nsCAutoString spec;
if (mURL) {
mURL->GetSpec(spec);
}
PR_LOG(gLog, PR_LOG_ALWAYS,
("rdfxml[%p] refresh(%s) %sblocking", this, mOriginalURLSpec.get(), (aBlocking ? "" : "non")));
("rdfxml[%p] refresh(%s) %sblocking", this, spec.get(), (aBlocking ? "" : "non")));
#endif
// If an asynchronous load is already pending, then just let it do
// the honors.
if (IsLoading()) {
PR_LOG(gLog, PR_LOG_ALWAYS,
("rdfxml[%p] refresh(%s) a load was pending", this, mOriginalURLSpec.get()));
("rdfxml[%p] refresh(%s) a load was pending", this, spec.get()));
if (aBlocking) {
NS_WARNING("blocking load requested when async load pending");
@ -955,9 +964,15 @@ RDFXMLDataSourceImpl::Refresh(PRBool aBlocking)
NS_IMETHODIMP
RDFXMLDataSourceImpl::BeginLoad(void)
{
#ifdef PR_LOGGING
nsCAutoString spec;
if (mURL) {
mURL->GetSpec(spec);
}
PR_LOG(gLog, PR_LOG_ALWAYS,
("rdfxml[%p] begin-load(%s)", this, mOriginalURLSpec.get()));
("rdfxml[%p] begin-load(%s)", this, spec.get()));
#endif
mLoadState = eLoadState_Loading;
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
nsIRDFXMLSinkObserver* obs =
@ -971,9 +986,15 @@ RDFXMLDataSourceImpl::BeginLoad(void)
NS_IMETHODIMP
RDFXMLDataSourceImpl::Interrupt(void)
{
#ifdef PR_LOGGING
nsCAutoString spec;
if (mURL) {
mURL->GetSpec(spec);
}
PR_LOG(gLog, PR_LOG_ALWAYS,
("rdfxml[%p] interrupt(%s)", this, mOriginalURLSpec.get()));
("rdfxml[%p] interrupt(%s)", this, spec.get()));
#endif
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
nsIRDFXMLSinkObserver* obs =
NS_STATIC_CAST(nsIRDFXMLSinkObserver*, mObservers[i]);
@ -986,9 +1007,15 @@ RDFXMLDataSourceImpl::Interrupt(void)
NS_IMETHODIMP
RDFXMLDataSourceImpl::Resume(void)
{
#ifdef PR_LOGGING
nsCAutoString spec;
if (mURL) {
mURL->GetSpec(spec);
}
PR_LOG(gLog, PR_LOG_ALWAYS,
("rdfxml[%p] resume(%s)", this, mOriginalURLSpec.get()));
("rdfxml[%p] resume(%s)", this, spec.get()));
#endif
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
nsIRDFXMLSinkObserver* obs =
NS_STATIC_CAST(nsIRDFXMLSinkObserver*, mObservers[i]);
@ -1001,9 +1028,15 @@ RDFXMLDataSourceImpl::Resume(void)
NS_IMETHODIMP
RDFXMLDataSourceImpl::EndLoad(void)
{
#ifdef PR_LOGGING
nsCAutoString spec;
if (mURL) {
mURL->GetSpec(spec);
}
PR_LOG(gLog, PR_LOG_ALWAYS,
("rdfxml[%p] end-load(%s)", this, mOriginalURLSpec.get()));
("rdfxml[%p] end-load(%s)", this, spec.get()));
#endif
mLoadState = eLoadState_Loaded;
// Clear out any unmarked assertions from the datasource.

View File

@ -77,6 +77,9 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
static NS_DEFINE_CID(kXULPrototypeCacheCID, NS_XULPROTOTYPECACHE_CID);
// This comes from nsChromeRegistry.cpp
extern nsIChromeRegistry* gChromeRegistry;
//----------------------------------------------------------------------
//
// A channel that's used for loading cached chrome documents. Since a
@ -566,8 +569,12 @@ nsChromeProtocolHandler::NewURI(const nsACString &aSpec,
nsIURI *aBaseURI,
nsIURI **result)
{
NS_PRECONDITION(result, "Null out param");
nsresult rv;
*result = nsnull;
// Chrome: URLs (currently) have no additional structure beyond that provided
// by standard URLs, so there is no "outer" given to CreateInstance
@ -579,25 +586,67 @@ nsChromeProtocolHandler::NewURI(const nsACString &aSpec,
if (NS_FAILED(rv))
return rv;
return CallQueryInterface(url, result);
nsCOMPtr<nsIURI> uri(do_QueryInterface(url, &rv));
if (NS_FAILED(rv))
return rv;
// Canonify the "chrome:" URL; e.g., so that we collapse
// "chrome://navigator/content/" and "chrome://navigator/content"
// and "chrome://navigator/content/navigator.xul".
// Try the global cache first.
nsCOMPtr<nsIChromeRegistry> reg = gChromeRegistry;
// If that fails, the service has not been instantiated it; let's
// do that now.
if (!reg) {
reg = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
}
NS_ASSERTION(reg, "Must have a chrome registry by now");
rv = reg->Canonify(uri);
if (NS_FAILED(rv))
return rv;
*result = uri;
NS_ADDREF(*result);
return NS_OK;
}
NS_IMETHODIMP
nsChromeProtocolHandler::NewChannel(nsIURI* aURI,
nsIChannel* *aResult)
{
NS_ENSURE_ARG_POINTER(aURI);
NS_PRECONDITION(aResult, "Null out param");
#ifdef DEBUG
// Check that the uri we got is already canonified
nsresult debug_rv;
nsCOMPtr<nsIChromeRegistry> debugReg(do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &debug_rv));
if (NS_SUCCEEDED(debug_rv)) {
nsCOMPtr<nsIURI> debugClone;
debug_rv = aURI->Clone(getter_AddRefs(debugClone));
if (NS_SUCCEEDED(debug_rv)) {
debug_rv = debugReg->Canonify(debugClone);
if (NS_SUCCEEDED(debug_rv)) {
PRBool same;
debug_rv = aURI->Equals(debugClone, &same);
if (NS_SUCCEEDED(debug_rv)) {
NS_ASSERTION(same, "Non-canonified chrome uri passed to nsChromeProtocolHandler::NewChannel!");
}
}
}
}
#endif
nsresult rv;
nsCOMPtr<nsIChannel> result;
// Canonify the "chrome:" URL; e.g., so that we collapse
// "chrome://navigator/content/navigator.xul" and "chrome://navigator/content"
// and "chrome://navigator/content/navigator.xul".
nsCOMPtr<nsIChromeRegistry> reg(do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv));
if (NS_FAILED(rv)) return rv;
rv = reg->Canonify(aURI);
if (NS_FAILED(rv)) return rv;
// Check the prototype cache to see if we've already got the
// document in the cache.
nsCOMPtr<nsIXULPrototypeCache> cache =
@ -636,6 +685,12 @@ nsChromeProtocolHandler::NewChannel(nsIURI* aURI,
//aURI->GetSpec(getter_Copies(oldSpec));
//printf("*************************** %s\n", (const char*)oldSpec);
nsCOMPtr<nsIChromeRegistry> reg = gChromeRegistry;
if (!reg) {
reg = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
}
nsCAutoString spec;
rv = reg->ConvertChromeURL(aURI, spec);
if (NS_FAILED(rv)) return rv;

View File

@ -128,6 +128,8 @@ static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
class nsChromeRegistry;
nsIChromeRegistry* gChromeRegistry = nsnull;
#define CHROME_URI "http://www.mozilla.org/rdf/chrome#"
DEFINE_RDF_VOCAB(CHROME_URI, CHROME, selectedSkin);
@ -288,6 +290,8 @@ static PRBool PR_CALLBACK DatasourceEnumerator(nsHashKey *aKey, void *aData, voi
nsChromeRegistry::~nsChromeRegistry()
{
gChromeRegistry = nsnull;
if (mDataSourceTable) {
mDataSourceTable->Enumerate(DatasourceEnumerator, mChromeDataSource);
delete mDataSourceTable;
@ -313,6 +317,8 @@ NS_IMPL_THREADSAFE_ISUPPORTS4(nsChromeRegistry, nsIChromeRegistry, nsIXULChromeR
nsresult
nsChromeRegistry::Init()
{
gChromeRegistry = this;
nsresult rv;
rv = nsServiceManager::GetService(kRDFServiceCID,
NS_GET_IID(nsIRDFService),