Bug 1420954 - Add NS_MutateURI helper function to chain nsIURIMutator setters in C++ r=bagder
MozReview-Commit-ID: 79NlOm08ebz
--- a/netwerk/base/moz.build
+++ b/netwerk/base/moz.build
@@ -207,16 +207,17 @@ UNIFIED_SOURCES += [
'nsDNSPrefetch.cpp',
'nsDownloader.cpp',
'nsFileStreams.cpp',
'nsIncrementalDownload.cpp',
'nsIncrementalStreamLoader.cpp',
'nsInputStreamChannel.cpp',
'nsInputStreamPump.cpp',
'nsIOService.cpp',
+ 'nsIURIMutatorUtils.cpp',
'nsLoadGroup.cpp',
'nsMediaFragmentURIParser.cpp',
'nsMIMEInputStream.cpp',
'nsNetAddr.cpp',
'nsNetUtil.cpp',
'nsPACMan.cpp',
'nsPreloadedStream.cpp',
'nsProtocolProxyService.cpp',
--- a/netwerk/base/nsIURIMutator.idl
+++ b/netwerk/base/nsIURIMutator.idl
@@ -5,24 +5,24 @@
#include "nsISupports.idl"
interface nsIURI;
interface nsIObjectInputStream;
interface nsIURIMutator;
%{C++
#include "nsStringGlue.h"
+#include "nsCOMPtr.h"
#undef SetPort // XXX Windows!
namespace mozilla {
class Encoding;
}
-
namespace mozilla {
namespace ipc {
class URIParams;
} // namespace ipc
} // namespace mozilla
template <class T>
class BaseURIMutator
@@ -84,17 +84,17 @@ protected:
#define NS_DEFINE_NSIMUTATOR_COMMON \
NS_IMETHOD Deserialize(const mozilla::ipc::URIParams& aParams) override \
{ return InitFromIPCParams(aParams); } \
NS_IMETHOD Read(nsIObjectInputStream* aStream) override \
{ return InitFromInputStream(aStream); } \
NS_IMETHOD Finalize(nsIURI** aURI) override \
{ mURI.forget(aURI); return NS_OK; } \
NS_IMETHOD SetSpec(const nsACString & aSpec, nsIURIMutator** aMutator) override \
- { NS_ADDREF(*aMutator = this); return InitFromSpec(aSpec); }
+ { if (aMutator) NS_ADDREF(*aMutator = this); return InitFromSpec(aSpec); }
%}
[ptr] native Encoding(const mozilla::Encoding);
[ref] native const_URIParams_ref(const mozilla::ipc::URIParams);
[scriptable, builtinclass, uuid(1fc53257-898b-4c5e-b69c-05bc84b4cd8f)]
interface nsIURISetSpec : nsISupports
{
@@ -133,43 +133,43 @@ interface nsIURISetters : nsIURISetSpec
nsIURIMutator setQuery(in AUTF8String aQuery);
[noscript] nsIURIMutator setQueryWithEncoding(in AUTF8String query, in Encoding encoding);
};
%{C++
// Using this macro instead of NS_FORWARD_SAFE_NSIURISETTERS makes chaining
// setter operations possible.
-#define NS_FORWARD_SAFE_NSIURISETTERS_RET(_to) \
- NS_IMETHOD SetScheme(const nsACString & aScheme, nsIURIMutator** aMutator) override \
- { NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetScheme(aScheme); } \
- NS_IMETHOD SetUserPass(const nsACString & aUserPass, nsIURIMutator** aMutator) override \
- { NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetUserPass(aUserPass); } \
- NS_IMETHOD SetUsername(const nsACString & aUsername, nsIURIMutator** aMutator) override \
- { NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetUsername(aUsername); } \
- NS_IMETHOD SetPassword(const nsACString & aPassword, nsIURIMutator** aMutator) override \
- { NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetPassword(aPassword); } \
- NS_IMETHOD SetHostPort(const nsACString & aHostPort, nsIURIMutator** aMutator) override \
- { NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetHostPort(aHostPort); } \
- NS_IMETHOD SetHostAndPort(const nsACString & aHostAndPort, nsIURIMutator** aMutator) override \
- { NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetHostAndPort(aHostAndPort); } \
- NS_IMETHOD SetHost(const nsACString & aHost, nsIURIMutator** aMutator) override \
- { NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetHost(aHost); } \
- NS_IMETHOD SetPort(int32_t aPort, nsIURIMutator** aMutator) override \
- { NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetPort(aPort); } \
- NS_IMETHOD SetPathQueryRef(const nsACString & aPathQueryRef, nsIURIMutator** aMutator) override \
- { NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetPathQueryRef(aPathQueryRef); } \
- NS_IMETHOD SetRef(const nsACString & aRef, nsIURIMutator** aMutator) override \
- { NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetRef(aRef); } \
- NS_IMETHOD SetFilePath(const nsACString & aFilePath, nsIURIMutator** aMutator) override \
- { NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetFilePath(aFilePath); } \
- NS_IMETHOD SetQuery(const nsACString & aQuery, nsIURIMutator** aMutator) override \
- { NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetQuery(aQuery); } \
- NS_IMETHOD SetQueryWithEncoding(const nsACString & query, const mozilla::Encoding *encoding, nsIURIMutator** aMutator) override \
- { NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetQueryWithEncoding(query, encoding); }
+#define NS_FORWARD_SAFE_NSIURISETTERS_RET(_to) \
+ NS_IMETHOD SetScheme(const nsACString & aScheme, nsIURIMutator** aMutator) override \
+ { if (aMutator) NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetScheme(aScheme); } \
+ NS_IMETHOD SetUserPass(const nsACString & aUserPass, nsIURIMutator** aMutator) override \
+ { if (aMutator) NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetUserPass(aUserPass); } \
+ NS_IMETHOD SetUsername(const nsACString & aUsername, nsIURIMutator** aMutator) override \
+ { if (aMutator) NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetUsername(aUsername); } \
+ NS_IMETHOD SetPassword(const nsACString & aPassword, nsIURIMutator** aMutator) override \
+ { if (aMutator) NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetPassword(aPassword); } \
+ NS_IMETHOD SetHostPort(const nsACString & aHostPort, nsIURIMutator** aMutator) override \
+ { if (aMutator) NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetHostPort(aHostPort); } \
+ NS_IMETHOD SetHostAndPort(const nsACString & aHostAndPort, nsIURIMutator** aMutator) override \
+ { if (aMutator) NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetHostAndPort(aHostAndPort); } \
+ NS_IMETHOD SetHost(const nsACString & aHost, nsIURIMutator** aMutator) override \
+ { if (aMutator) NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetHost(aHost); } \
+ NS_IMETHOD SetPort(int32_t aPort, nsIURIMutator** aMutator) override \
+ { if (aMutator) NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetPort(aPort); } \
+ NS_IMETHOD SetPathQueryRef(const nsACString & aPathQueryRef, nsIURIMutator** aMutator) override \
+ { if (aMutator) NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetPathQueryRef(aPathQueryRef); } \
+ NS_IMETHOD SetRef(const nsACString & aRef, nsIURIMutator** aMutator) override \
+ { if (aMutator) NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetRef(aRef); } \
+ NS_IMETHOD SetFilePath(const nsACString & aFilePath, nsIURIMutator** aMutator) override \
+ { if (aMutator) NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetFilePath(aFilePath); } \
+ NS_IMETHOD SetQuery(const nsACString & aQuery, nsIURIMutator** aMutator) override \
+ { if (aMutator) NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetQuery(aQuery); } \
+ NS_IMETHOD SetQueryWithEncoding(const nsACString & query, const mozilla::Encoding *encoding, nsIURIMutator** aMutator) override \
+ { if (aMutator) NS_ADDREF(*aMutator = this); return !_to ? NS_ERROR_NULL_POINTER : _to->SetQueryWithEncoding(query, encoding); }
%}
[scriptable, builtinclass, uuid(4d1f3103-1c44-4dcd-b717-5d22a697a7d9)]
interface nsIURIMutator : nsIURISetters
{
/**
* Initializes the URI by reading from the input stream.
@@ -186,8 +186,114 @@ interface nsIURIMutator : nsIURISetters
nsresult deserialize(in const_URIParams_ref aParams);
/**
* Finishes changing or constructing the URI and returns an immutable URI.
*/
nsIURI finalize();
};
+%{C++
+
+// This class provides a useful helper that allows chaining of setter operations
+class MOZ_STACK_CLASS NS_MutateURI
+{
+public:
+ explicit NS_MutateURI(nsIURI* aURI);
+ explicit NS_MutateURI(const char * aContractID);
+
+ NS_MutateURI& SetSpec(const nsACString& aSpec)
+ {
+ NS_ENSURE_SUCCESS(mStatus, *this);
+ mStatus = mMutator->SetSpec(aSpec, nullptr);
+ return *this;
+ }
+ NS_MutateURI& SetScheme(const nsACString& aScheme)
+ {
+ NS_ENSURE_SUCCESS(mStatus, *this);
+ mStatus = mMutator->SetScheme(aScheme, nullptr);
+ return *this;
+ }
+ NS_MutateURI& SetUserPass(const nsACString& aUserPass)
+ {
+ NS_ENSURE_SUCCESS(mStatus, *this);
+ mStatus = mMutator->SetUserPass(aUserPass, nullptr);
+ return *this;
+ }
+ NS_MutateURI& SetUsername(const nsACString& aUsername)
+ {
+ NS_ENSURE_SUCCESS(mStatus, *this);
+ mStatus = mMutator->SetUsername(aUsername, nullptr);
+ return *this;
+ }
+ NS_MutateURI& SetPassword(const nsACString& aPassword)
+ {
+ NS_ENSURE_SUCCESS(mStatus, *this);
+ mStatus = mMutator->SetPassword(aPassword, nullptr);
+ return *this;
+ }
+ NS_MutateURI& SetHostPort(const nsACString& aHostPort)
+ {
+ NS_ENSURE_SUCCESS(mStatus, *this);
+ mStatus = mMutator->SetHostPort(aHostPort, nullptr);
+ return *this;
+ }
+ NS_MutateURI& SetHostAndPort(const nsACString& aHostAndPort)
+ {
+ NS_ENSURE_SUCCESS(mStatus, *this);
+ mStatus = mMutator->SetHostAndPort(aHostAndPort, nullptr);
+ return *this;
+ }
+ NS_MutateURI& SetHost(const nsACString& aHost)
+ {
+ NS_ENSURE_SUCCESS(mStatus, *this);
+ mStatus = mMutator->SetHost(aHost, nullptr);
+ return *this;
+ }
+ NS_MutateURI& SetPort(int32_t aPort)
+ {
+ NS_ENSURE_SUCCESS(mStatus, *this);
+ mStatus = mMutator->SetPort(aPort, nullptr);
+ return *this;
+ }
+ NS_MutateURI& SetPathQueryRef(const nsACString& aPathQueryRef)
+ {
+ NS_ENSURE_SUCCESS(mStatus, *this);
+ mStatus = mMutator->SetPathQueryRef(aPathQueryRef, nullptr);
+ return *this;
+ }
+ NS_MutateURI& SetRef(const nsACString& aRef)
+ {
+ NS_ENSURE_SUCCESS(mStatus, *this);
+ mStatus = mMutator->SetRef(aRef, nullptr);
+ return *this;
+ }
+ NS_MutateURI& SetFilePath(const nsACString& aFilePath)
+ {
+ NS_ENSURE_SUCCESS(mStatus, *this);
+ mStatus = mMutator->SetFilePath(aFilePath, nullptr);
+ return *this;
+ }
+ NS_MutateURI& SetQuery(const nsACString& aQuery)
+ {
+ NS_ENSURE_SUCCESS(mStatus, *this);
+ mStatus = mMutator->SetQuery(aQuery, nullptr);
+ return *this;
+ }
+ NS_MutateURI& SetQueryWithEncoding(const nsACString& query, const mozilla::Encoding *encoding)
+ {
+ NS_ENSURE_SUCCESS(mStatus, *this);
+ mStatus = mMutator->SetQueryWithEncoding(query, encoding, nullptr);
+ return *this;
+ }
+ nsresult Finalize(nsIURI** aURI)
+ {
+ NS_ENSURE_SUCCESS(mStatus, mStatus);
+ mStatus = mMutator->Finalize(aURI);
+ return mStatus;
+ }
+ nsresult GetStatus() { return mStatus; }
+private:
+ nsresult mStatus;
+ RefPtr<nsIURIMutator> mMutator;
+};
+
+%}
new file mode 100644
--- /dev/null
+++ b/netwerk/base/nsIURIMutatorUtils.cpp
@@ -0,0 +1,22 @@
+#include "nsIURIMutator.h"
+#include "nsIURI.h"
+#include "nsComponentManagerUtils.h"
+
+static nsresult
+GetURIMutator(nsIURI* aURI, nsIURIMutator** aMutator)
+{
+ if (NS_WARN_IF(!aURI)) {
+ return NS_ERROR_INVALID_ARG;
+ }
+ return aURI->Mutate(aMutator);
+}
+
+NS_MutateURI::NS_MutateURI(nsIURI* aURI)
+{
+ mStatus = GetURIMutator(aURI, getter_AddRefs(mMutator));
+}
+
+NS_MutateURI::NS_MutateURI(const char * aContractID)
+{
+ mMutator = do_CreateInstance(aContractID, &mStatus);
+}
--- a/netwerk/test/gtest/TestStandardURL.cpp
+++ b/netwerk/test/gtest/TestStandardURL.cpp
@@ -2,17 +2,17 @@
#include "gtest/MozGTestBench.h" // For MOZ_GTEST_BENCH
#include "nsCOMPtr.h"
#include "nsNetCID.h"
#include "nsIURL.h"
#include "nsString.h"
#include "nsPrintfCString.h"
#include "nsComponentManagerUtils.h"
-
+#include "nsIURIMutator.h"
// In nsStandardURL.cpp
extern nsresult Test_NormalizeIPv4(const nsACString& host, nsCString& result);
TEST(TestStandardURL, Simple) {
nsCOMPtr<nsIURL> url( do_CreateInstance(NS_STANDARDURL_CONTRACTID) );
ASSERT_TRUE(url);
@@ -230,8 +230,32 @@ MOZ_GTEST_BENCH(TestStandardURL, Normali
ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost3, result));
nsAutoCString encHost4("111.159.notonmywatch.220");
ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost4, result));
nsAutoCString encHost5("1.160.204.20f");
ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost5, result));
}
});
#endif
+
+
+TEST(TestStandardURL, Mutator)
+{
+ nsAutoCString out;
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
+ .SetSpec(NS_LITERAL_CSTRING("http://example.com"))
+ .Finalize(getter_AddRefs(uri));
+ ASSERT_EQ(rv, NS_OK);
+
+ ASSERT_EQ(uri->GetSpec(out), NS_OK);
+ ASSERT_TRUE(out == NS_LITERAL_CSTRING("http://example.com/"));
+
+ nsCOMPtr<nsIURI> uri2;
+ rv = NS_MutateURI(uri)
+ .SetScheme(NS_LITERAL_CSTRING("ftp"))
+ .SetHost(NS_LITERAL_CSTRING("mozilla.org"))
+ .SetPathQueryRef(NS_LITERAL_CSTRING("/path?query#ref"))
+ .Finalize(getter_AddRefs(uri2));
+ ASSERT_EQ(rv, NS_OK);
+ ASSERT_EQ(uri2->GetSpec(out), NS_OK);
+ ASSERT_TRUE(out == NS_LITERAL_CSTRING("ftp://mozilla.org/path?query#ref"));
+}