Bug 308590 patch 3.5: Add nsIURI::CloneIgnoringRef interface & impls. r=bz sr=biesi
--- a/caps/src/nsNullPrincipalURI.cpp
+++ b/caps/src/nsNullPrincipalURI.cpp
@@ -232,22 +232,29 @@ nsNullPrincipalURI::SetUserPass(const ns
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsNullPrincipalURI::Clone(nsIURI **_newURI)
{
nsCOMPtr<nsIURI> uri =
new nsNullPrincipalURI(mScheme + NS_LITERAL_CSTRING(":") + mPath);
- NS_ENSURE_TRUE(uri, NS_ERROR_OUT_OF_MEMORY);
uri.forget(_newURI);
return NS_OK;
}
NS_IMETHODIMP
+nsNullPrincipalURI::CloneIgnoringRef(nsIURI **_newURI)
+{
+ // GetRef/SetRef not supported by nsNullPrincipalURI, so
+ // CloneIgnoringRef() is the same as Clone().
+ return Clone(_newURI);
+}
+
+NS_IMETHODIMP
nsNullPrincipalURI::Equals(nsIURI *aOther, PRBool *_equals)
{
*_equals = PR_FALSE;
nsNullPrincipalURI *otherURI;
nsresult rv = aOther->QueryInterface(kNullPrincipalURIImplementationCID,
(void **)&otherURI);
if (NS_SUCCEEDED(rv)) {
*_equals = (mScheme == otherURI->mScheme && mPath == otherURI->mPath);
--- a/content/base/src/nsFileDataProtocolHandler.cpp
+++ b/content/base/src/nsFileDataProtocolHandler.cpp
@@ -142,24 +142,25 @@ public:
// For use only from deserialization
nsFileDataURI() : nsSimpleURI() {}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIURIWITHPRINCIPAL
NS_DECL_NSISERIALIZABLE
NS_DECL_NSICLASSINFO
- // Override Clone() and EqualsInternal()
- NS_IMETHOD Clone(nsIURI** aClone);
+ // Override CloneInternal() and EqualsInternal()
+ virtual nsresult CloneInternal(RefHandlingEnum aRefHandlingMode,
+ nsIURI** aClone);
virtual nsresult EqualsInternal(nsIURI* aOther,
RefHandlingEnum aRefHandlingMode,
PRBool* aResult);
// Override StartClone to hand back a nsFileDataURI
- virtual nsSimpleURI* StartClone()
+ virtual nsSimpleURI* StartClone(RefHandlingEnum /* unused */)
{ return new nsFileDataURI(); }
nsCOMPtr<nsIPrincipal> mPrincipal;
};
NS_IMPL_ADDREF_INHERITED(nsFileDataURI, nsSimpleURI)
NS_IMPL_RELEASE_INHERITED(nsFileDataURI, nsSimpleURI)
NS_INTERFACE_MAP_BEGIN(nsFileDataURI)
@@ -210,22 +211,23 @@ nsFileDataURI::Write(nsIObjectOutputStre
NS_ENSURE_SUCCESS(rv, rv);
return NS_WriteOptionalCompoundObject(aStream, mPrincipal,
NS_GET_IID(nsIPrincipal),
PR_TRUE);
}
// nsIURI methods:
-
-NS_IMETHODIMP
-nsFileDataURI::Clone(nsIURI** aClone)
+nsresult
+nsFileDataURI::CloneInternal(nsSimpleURI::RefHandlingEnum aRefHandlingMode,
+ nsIURI** aClone)
{
nsCOMPtr<nsIURI> simpleClone;
- nsresult rv = nsSimpleURI::Clone(getter_AddRefs(simpleClone));
+ nsresult rv =
+ nsSimpleURI::CloneInternal(aRefHandlingMode, getter_AddRefs(simpleClone));
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG
nsRefPtr<nsFileDataURI> uriCheck;
rv = simpleClone->QueryInterface(kFILEDATAURICID, getter_AddRefs(uriCheck));
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) && uriCheck,
"Unexpected!");
#endif
--- a/modules/libjar/nsJARURI.cpp
+++ b/modules/libjar/nsJARURI.cpp
@@ -509,17 +509,29 @@ nsJARURI::SchemeIs(const char *i_Scheme,
}
NS_IMETHODIMP
nsJARURI::Clone(nsIURI **result)
{
nsresult rv;
nsCOMPtr<nsIJARURI> uri;
- rv = CloneWithJARFile(mJARFile, getter_AddRefs(uri));
+ rv = CloneWithJARFileInternal(mJARFile, eHonorRef, getter_AddRefs(uri));
+ if (NS_FAILED(rv)) return rv;
+
+ return CallQueryInterface(uri, result);
+}
+
+NS_IMETHODIMP
+nsJARURI::CloneIgnoringRef(nsIURI **result)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIJARURI> uri;
+ rv = CloneWithJARFileInternal(mJARFile, eIgnoreRef, getter_AddRefs(uri));
if (NS_FAILED(rv)) return rv;
return CallQueryInterface(uri, result);
}
NS_IMETHODIMP
nsJARURI::Resolve(const nsACString &relativePath, nsACString &result)
{
@@ -777,47 +789,53 @@ nsJARURI::SetJAREntry(const nsACString &
{
return CreateEntryURL(entryPath, mCharsetHint.get(),
getter_AddRefs(mJAREntry));
}
NS_IMETHODIMP
nsJARURI::CloneWithJARFile(nsIURI *jarFile, nsIJARURI **result)
{
+ return CloneWithJARFileInternal(jarFile, eHonorRef, result);
+}
+
+nsresult
+nsJARURI::CloneWithJARFileInternal(nsIURI *jarFile,
+ nsJARURI::RefHandlingEnum refHandlingMode,
+ nsIJARURI **result)
+{
if (!jarFile) {
return NS_ERROR_INVALID_ARG;
}
nsresult rv;
nsCOMPtr<nsIURI> newJARFile;
rv = jarFile->Clone(getter_AddRefs(newJARFile));
if (NS_FAILED(rv)) return rv;
NS_TryToSetImmutable(newJARFile);
nsCOMPtr<nsIURI> newJAREntryURI;
- rv = mJAREntry->Clone(getter_AddRefs(newJAREntryURI));
+ rv = refHandlingMode == eHonorRef ?
+ mJAREntry->Clone(getter_AddRefs(newJAREntryURI)) :
+ mJAREntry->CloneIgnoringRef(getter_AddRefs(newJAREntryURI));
+
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIURL> newJAREntry(do_QueryInterface(newJAREntryURI));
NS_ASSERTION(newJAREntry, "This had better QI to nsIURL!");
nsJARURI* uri = new nsJARURI();
- if (uri) {
- NS_ADDREF(uri);
- uri->mJARFile = newJARFile;
- uri->mJAREntry = newJAREntry;
- *result = uri;
- rv = NS_OK;
- } else {
- rv = NS_ERROR_OUT_OF_MEMORY;
- }
+ NS_ADDREF(uri);
+ uri->mJARFile = newJARFile;
+ uri->mJAREntry = newJAREntry;
+ *result = uri;
- return rv;
+ return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsJARURI::GetInnerURI(nsIURI **uri)
{
return NS_EnsureSafeToReturn(mJARFile, uri);
--- a/modules/libjar/nsJARURI.h
+++ b/modules/libjar/nsJARURI.h
@@ -100,16 +100,20 @@ protected:
eHonorRef
};
// Helper to share code between Equals methods.
virtual nsresult EqualsInternal(nsIURI* other,
RefHandlingEnum refHandlingMode,
PRBool* result);
+ // Helper to share code between Clone methods.
+ nsresult CloneWithJARFileInternal(nsIURI *jarFile,
+ RefHandlingEnum refHandlingMode,
+ nsIJARURI **result);
nsCOMPtr<nsIURI> mJARFile;
// mJarEntry stored as a URL so that we can easily access things
// like extensions, refs, etc.
nsCOMPtr<nsIURL> mJAREntry;
nsCString mCharsetHint;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsJARURI, NS_THIS_JARURI_IMPL_CID)
--- a/modules/libpr0n/decoders/icon/nsIconURI.cpp
+++ b/modules/libpr0n/decoders/icon/nsIconURI.cpp
@@ -444,32 +444,37 @@ nsMozIconURI::Clone(nsIURI **result)
if (NS_FAILED(rv))
return rv;
newIconURL = do_QueryInterface(newURI, &rv);
if (NS_FAILED(rv))
return rv;
}
nsMozIconURI *uri = new nsMozIconURI();
- if (!uri)
- return NS_ERROR_OUT_OF_MEMORY;
-
newIconURL.swap(uri->mIconURL);
uri->mSize = mSize;
uri->mContentType = mContentType;
uri->mFileName = mFileName;
uri->mStockIcon = mStockIcon;
uri->mIconSize = mIconSize;
uri->mIconState = mIconState;
NS_ADDREF(*result = uri);
return NS_OK;
}
NS_IMETHODIMP
+nsMozIconURI::CloneIgnoringRef(nsIURI **result)
+{
+ // GetRef/SetRef not supported by nsMozIconURI, so
+ // CloneIgnoringRef() is the same as Clone().
+ return Clone(result);
+}
+
+NS_IMETHODIMP
nsMozIconURI::Resolve(const nsACString &relativePath, nsACString &result)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMozIconURI::GetAsciiSpec(nsACString &aSpecA)
{
--- a/netwerk/base/public/nsIURI.idl
+++ b/netwerk/base/public/nsIURI.idl
@@ -215,16 +215,21 @@ interface nsIURI : nsISupports
boolean schemeIs(in string scheme);
/**
* Clones the current URI.
*/
nsIURI clone();
/**
+ * Clones the current URI, clearing the 'ref' attribute in the clone.
+ */
+ nsIURI cloneIgnoringRef();
+
+ /**
* This method resolves a relative string into an absolute URI string,
* using this URI as the base.
*
* NOTE: some implementations may have no concept of a relative URI.
*/
AUTF8String resolve(in AUTF8String relativePath);
--- a/netwerk/base/src/nsSimpleNestedURI.cpp
+++ b/netwerk/base/src/nsSimpleNestedURI.cpp
@@ -157,22 +157,25 @@ nsSimpleNestedURI::EqualsInternal(nsIURI
}
}
}
return NS_OK;
}
/* virtual */ nsSimpleURI*
-nsSimpleNestedURI::StartClone()
+nsSimpleNestedURI::StartClone(nsSimpleURI::RefHandlingEnum refHandlingMode)
{
NS_ENSURE_TRUE(mInnerURI, nsnull);
nsCOMPtr<nsIURI> innerClone;
- nsresult rv = mInnerURI->Clone(getter_AddRefs(innerClone));
+ nsresult rv = refHandlingMode == eHonorRef ?
+ mInnerURI->Clone(getter_AddRefs(innerClone)) :
+ mInnerURI->CloneIgnoringRef(getter_AddRefs(innerClone));
+
if (NS_FAILED(rv)) {
return nsnull;
}
nsSimpleNestedURI* url = new nsSimpleNestedURI(innerClone);
if (url) {
url->SetMutable(PR_FALSE);
}
--- a/netwerk/base/src/nsSimpleNestedURI.h
+++ b/netwerk/base/src/nsSimpleNestedURI.h
@@ -72,17 +72,17 @@ public:
NS_DECL_NSIIPCSERIALIZABLE
// Overrides for various methods nsSimpleURI implements follow.
// nsSimpleURI overrides
virtual nsresult EqualsInternal(nsIURI* other,
RefHandlingEnum refHandlingMode,
PRBool* result);
- virtual nsSimpleURI* StartClone();
+ virtual nsSimpleURI* StartClone(RefHandlingEnum refHandlingMode);
// nsISerializable overrides
NS_IMETHOD Read(nsIObjectInputStream* aStream);
NS_IMETHOD Write(nsIObjectOutputStream* aStream);
// Override the nsIClassInfo method GetClassIDNoAlloc to make sure our
// nsISerializable impl works right.
NS_IMETHOD GetClassIDNoAlloc(nsCID *aClassIDNoAlloc);
--- a/netwerk/base/src/nsSimpleURI.cpp
+++ b/netwerk/base/src/nsSimpleURI.cpp
@@ -390,25 +390,40 @@ nsSimpleURI::SchemeIs(const char *i_Sche
} else {
*o_Equals = PR_FALSE;
}
return NS_OK;
}
/* virtual */ nsSimpleURI*
-nsSimpleURI::StartClone()
+nsSimpleURI::StartClone(nsSimpleURI::RefHandlingEnum /* ignored */)
{
return new nsSimpleURI();
}
NS_IMETHODIMP
-nsSimpleURI::Clone(nsIURI* *result)
+nsSimpleURI::Clone(nsIURI** result)
+{
+ return CloneInternal(eHonorRef, result);
+}
+
+NS_IMETHODIMP
+nsSimpleURI::CloneIgnoringRef(nsIURI** result)
{
- nsSimpleURI* url = StartClone();
+ return CloneInternal(eIgnoreRef, result);
+}
+
+nsresult
+nsSimpleURI::CloneInternal(nsSimpleURI::RefHandlingEnum refHandlingMode,
+ nsIURI** result)
+{
+ // XXXdholbert Mostly ignoring refHandlingMode so far, but I'll make use
+ // of it in next patch, when I add support for .ref to this class.
+ nsSimpleURI* url = StartClone(refHandlingMode);
if (url == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
// Note: |url| may well have mMutable false at this point, so
// don't call any setter methods.
url->mScheme = mScheme;
url->mPath = mPath;
--- a/netwerk/base/src/nsSimpleURI.h
+++ b/netwerk/base/src/nsSimpleURI.h
@@ -75,22 +75,28 @@ public:
protected:
// enum used in a few places to specify how .ref attribute should be handled
enum RefHandlingEnum {
eIgnoreRef,
eHonorRef
};
- // Helper to share code between Equals methods. Subclasses can override
- // for custom Equals behavior.
+ // Helper to share code between Equals methods.
virtual nsresult EqualsInternal(nsIURI* other,
RefHandlingEnum refHandlingMode,
PRBool* result);
- virtual nsSimpleURI* StartClone();
+ // NOTE: This takes the refHandlingMode as an argument because
+ // nsSimpleNestedURI's specialized version needs to know how to clone
+ // its inner URI.
+ virtual nsSimpleURI* StartClone(RefHandlingEnum refHandlingMode);
+ // Helper to share code between Clone methods.
+ virtual nsresult CloneInternal(RefHandlingEnum refHandlingMode,
+ nsIURI** clone);
+
nsCString mScheme;
nsCString mPath;
PRBool mMutable;
};
#endif // nsSimpleURI_h__
--- a/netwerk/base/src/nsStandardURL.cpp
+++ b/netwerk/base/src/nsStandardURL.cpp
@@ -1692,17 +1692,32 @@ nsStandardURL::StartClone()
{
nsStandardURL *clone = new nsStandardURL();
return clone;
}
NS_IMETHODIMP
nsStandardURL::Clone(nsIURI **result)
{
- nsStandardURL *clone = StartClone();
+ return CloneInternal(eHonorRef, result);
+}
+
+
+NS_IMETHODIMP
+nsStandardURL::CloneIgnoringRef(nsIURI **result)
+{
+ return CloneInternal(eIgnoreRef, result);
+}
+
+nsresult
+nsStandardURL::CloneInternal(nsStandardURL::RefHandlingEnum refHandlingMode,
+ nsIURI **result)
+
+{
+ nsRefPtr<nsStandardURL> clone = StartClone();
if (!clone)
return NS_ERROR_OUT_OF_MEMORY;
clone->mSpec = mSpec;
clone->mDefaultPort = mDefaultPort;
clone->mPort = mPort;
clone->mScheme = mScheme;
clone->mAuthority = mAuthority;
@@ -1722,17 +1737,21 @@ nsStandardURL::Clone(nsIURI **result)
clone->mParser = mParser;
clone->mFile = mFile;
clone->mHostA = mHostA ? nsCRT::strdup(mHostA) : nsnull;
clone->mMutable = PR_TRUE;
clone->mSupportsFileURL = mSupportsFileURL;
clone->mHostEncoding = mHostEncoding;
clone->mSpecEncoding = mSpecEncoding;
- NS_ADDREF(*result = clone);
+ if (refHandlingMode == eIgnoreRef) {
+ clone->SetRef(EmptyCString());
+ }
+
+ clone.forget(result);
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::Resolve(const nsACString &in, nsACString &out)
{
const nsPromiseFlatCString &flat = PromiseFlatCString(in);
const char *relpath = flat.get();
--- a/netwerk/base/src/nsStandardURL.h
+++ b/netwerk/base/src/nsStandardURL.h
@@ -162,16 +162,20 @@ protected:
// Helper to share code between Equals and EqualsExceptRef
// NOTE: *not* virtual, because no one needs to override this so far...
nsresult EqualsInternal(nsIURI* unknownOther,
RefHandlingEnum refHandlingMode,
PRBool* result);
virtual nsStandardURL* StartClone();
+ // Helper to share code between Clone methods.
+ nsresult CloneInternal(RefHandlingEnum aRefHandlingMode,
+ nsIURI** aClone);
+
// Helper for subclass implementation of GetFile(). Subclasses that map
// URIs to files in a special way should implement this method. It should
// ensure that our mFile is initialized, if it's possible.
// returns NS_ERROR_NO_INTERFACE if the url does not map to a file
virtual nsresult EnsureFile();
private:
PRInt32 Port() { return mPort == -1 ? mDefaultPort : mPort; }
--- a/netwerk/test/unit/test_URIs.js
+++ b/netwerk/test/unit/test_URIs.js
@@ -191,16 +191,17 @@ function do_check_property(aTest, aURI,
// Test that a given URI parses correctly into its various components.
function do_test_uri_basic(aTest) {
var URI = NetUtil.newURI(aTest.spec);
// Sanity-check
do_info("testing " + aTest.spec + " equals a clone of itself");
do_check_uri_eq(URI, URI.clone());
+ do_check_uri_eq(URI, URI.cloneIgnoringRef());
do_info("testing " + aTest.spec + " instanceof nsIURL");
do_check_eq(URI instanceof Ci.nsIURL, aTest.nsIURL);
do_info("testing " + aTest.spec + " instanceof nsINestedURI");
do_check_eq(URI instanceof Ci.nsINestedURI,
aTest.nsINestedURI);
// Check the various components
do_check_property(aTest, URI, "scheme");
@@ -243,16 +244,27 @@ function do_test_uri_with_hash_suffix(aT
if (aTest.nsIURL) {
var URL = testURI.QueryInterface(Ci.nsIURL);
do_check_property(aTest, URL, "ref",
function(aStr) { return aSuffix.substr(1); });
do_info("testing " + aTest.spec +
" is equalExceptRef to self with '" + aSuffix + "' appended");
do_check_uri_eqExceptRef(origURI, testURI);
+
+ do_info("testing cloneIgnoringRef on " + testURI.spec +
+ " is equal to no-ref version but not equal to ref version");
+ var cloneNoRef = testURI.cloneIgnoringRef();
+ if (aTest.spec == "http://" && aSuffix == "#") {
+ do_info("TODO: bug 657033");
+ do_check_uri_eq(cloneNoRef, origURI, todo_check_true);
+ } else {
+ do_check_uri_eq(cloneNoRef, origURI);
+ }
+ do_check_false(cloneNoRef.equals(testURI));
}
}
// Tests various ways of setting & clearing a ref on a URI.
function do_test_mutate_ref(aTest, aSuffix) {
do_info("making sure caller is using suffix that starts with '#'");
do_check_eq(aSuffix[0], "#");