Bug 1420954 - Add NS_MutateURI helper function to chain nsIURIMutator setters in C++ r=bagder
☠☠ backed out by 7a19568290c6 ☠ ☠
authorValentin Gosu <valentin.gosu@gmail.com>
Sat, 02 Dec 2017 23:15:55 +0100
changeset 394754 8ce0a0d49d9e8789018c4322cdc61bcb346ac307
parent 394753 480c6e1721e9014d834dfe587178a423621c6fd5
child 394755 046bf5aa7d413e52bac10db33d0ab3bb5cb2d638
push id33019
push userbtara@mozilla.com
push dateMon, 04 Dec 2017 20:16:32 +0000
treeherdermozilla-central@4a003542df78 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbagder
bugs1420954
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1420954 - Add NS_MutateURI helper function to chain nsIURIMutator setters in C++ r=bagder MozReview-Commit-ID: 79NlOm08ebz
netwerk/base/nsIURIMutator.idl
netwerk/base/nsStandardURL.cpp
netwerk/test/gtest/TestStandardURL.cpp
--- a/netwerk/base/nsIURIMutator.idl
+++ b/netwerk/base/nsIURIMutator.idl
@@ -5,17 +5,19 @@
 
 #include "nsISupports.idl"
 interface nsIURI;
 interface nsIObjectInputStream;
 interface nsIURIMutator;
 
 %{C++
 #include "nsStringGlue.h"
+#include "nsCOMPtr.h"
 
+extern nsresult NS_GetURIMutator(nsIURI* aURI, nsIURIMutator** aMutator);
 #undef SetPort  // XXX Windows!
 
 namespace mozilla {
 class Encoding;
 }
 
 
 namespace mozilla {
@@ -84,17 +86,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 +135,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 +188,116 @@ 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:
+  NS_MutateURI(nsIURI* aURI)
+    { mStatus = NS_GetURIMutator(aURI, getter_AddRefs(mMutator)); }
+  NS_MutateURI(nsCOMPtr<nsIURIMutator> aMutator)
+    { mStatus = NS_OK; mMutator = aMutator; }
+
+  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;
+};
+
+%}
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -3763,8 +3763,14 @@ nsStandardURL::SizeOfIncludingThis(Mallo
 } // namespace mozilla
 
 // For unit tests.  Including nsStandardURL.h seems to cause problems
 nsresult
 Test_NormalizeIPv4(const nsACString& host, nsCString& result)
 {
     return nsStandardURL::NormalizeIPv4(host, result);
 }
+
+nsresult
+NS_GetURIMutator(nsIURI* aURI, nsIURIMutator** aMutator)
+{
+    return aURI->Mutate(aMutator);
+}
--- 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,31 @@ 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(do_CreateInstance(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/"));
+
+  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(uri));
+  ASSERT_EQ(rv, NS_OK);
+  ASSERT_EQ(uri->GetSpec(out), NS_OK);
+  ASSERT_TRUE(out == NS_LITERAL_CSTRING("ftp://mozilla.org/path?query#ref"));
+}