Bug 1420954 - Make nsIURIMutator setters return nsIURIMutator so we can chain setters r=bagder
authorValentin Gosu <valentin.gosu@gmail.com>
Tue, 05 Dec 2017 02:35:21 +0100
changeset 449429 0a1f4c9feba0a2508538142fa526a1f9ac2be088
parent 449428 27129356fbe41f7ed096d791deeaade557f3bd8b
child 449430 33570a2d4633a6fad41cbd706dd5bf2eb266720d
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [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 - Make nsIURIMutator setters return nsIURIMutator so we can chain setters r=bagder MozReview-Commit-ID: 53BD91hB2yi
caps/NullPrincipalURI.h
dom/file/nsHostObjectURI.h
dom/jsurl/nsJSProtocolHandler.h
image/decoders/icon/nsIconURI.h
modules/libjar/nsJARURI.h
netwerk/base/nsIURIMutator.idl
netwerk/base/nsSimpleNestedURI.h
netwerk/base/nsSimpleURI.h
netwerk/base/nsStandardURL.h
netwerk/protocol/about/nsAboutProtocolHandler.h
netwerk/test/unit/test_uri_mutator.js
netwerk/test/unit/xpcshell.ini
--- a/caps/NullPrincipalURI.h
+++ b/caps/NullPrincipalURI.h
@@ -53,17 +53,17 @@ private:
   nsAutoCStringN<NSID_LENGTH> mPath;
 
 public:
   class Mutator
       : public nsIURIMutator
       , public BaseURIMutator<NullPrincipalURI>
   {
     NS_DECL_ISUPPORTS
-    NS_FORWARD_SAFE_NSIURISETTERS(mURI)
+    NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
 
     NS_IMETHOD Deserialize(const mozilla::ipc::URIParams& aParams) override
     {
       return InitFromIPCParams(aParams);
     }
 
     NS_IMETHOD Read(nsIObjectInputStream* aStream) override
     {
@@ -71,18 +71,19 @@ public:
     }
 
     NS_IMETHOD Finalize(nsIURI** aURI) override
     {
       mURI.forget(aURI);
       return NS_OK;
     }
 
-    NS_IMETHOD SetSpec(const nsACString & aSpec) override
+    NS_IMETHOD SetSpec(const nsACString & aSpec, nsIURIMutator** aMutator) override
     {
+      NS_ADDREF(*aMutator = this);
       return NS_ERROR_NOT_IMPLEMENTED;
     }
 
     explicit Mutator() { }
   private:
     virtual ~Mutator() { }
 
     friend class NullPrincipalURI;
--- a/dom/file/nsHostObjectURI.h
+++ b/dom/file/nsHostObjectURI.h
@@ -78,17 +78,17 @@ protected:
   virtual ~nsHostObjectURI() {}
 
 public:
   class Mutator
     : public nsIURIMutator
     , public BaseURIMutator<nsHostObjectURI>
   {
     NS_DECL_ISUPPORTS
-    NS_FORWARD_SAFE_NSIURISETTERS(mURI)
+    NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
     NS_DEFINE_NSIMUTATOR_COMMON
 
     explicit Mutator() { }
   private:
     virtual ~Mutator() { }
 
     friend class nsHostObjectURI;
   };
--- a/dom/jsurl/nsJSProtocolHandler.h
+++ b/dom/jsurl/nsJSProtocolHandler.h
@@ -105,17 +105,17 @@ private:
     nsCOMPtr<nsIURI> mBaseURI;
 
 public:
     class Mutator
         : public nsIURIMutator
         , public BaseURIMutator<nsJSURI>
     {
         NS_DECL_ISUPPORTS
-        NS_FORWARD_SAFE_NSIURISETTERS(mURI)
+        NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
         NS_DEFINE_NSIMUTATOR_COMMON
 
         explicit Mutator() { }
     private:
         virtual ~Mutator() { }
 
         friend class nsJSURI;
     };
--- a/image/decoders/icon/nsIconURI.h
+++ b/image/decoders/icon/nsIconURI.h
@@ -46,17 +46,17 @@ protected:
                        // kStateStrings
 
 public:
   class Mutator
       : public nsIURIMutator
       , public BaseURIMutator<nsMozIconURI>
   {
     NS_DECL_ISUPPORTS
-    NS_FORWARD_SAFE_NSIURISETTERS(mURI)
+    NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
 
     NS_IMETHOD Deserialize(const mozilla::ipc::URIParams& aParams) override
     {
       return InitFromIPCParams(aParams);
     }
 
     NS_IMETHOD Read(nsIObjectInputStream* aStream) override
     {
@@ -64,17 +64,18 @@ public:
     }
 
     NS_IMETHOD Finalize(nsIURI** aURI) override
     {
       mURI.forget(aURI);
       return NS_OK;
     }
 
-    NS_IMETHOD SetSpec(const nsACString & aSpec) override {
+    NS_IMETHOD SetSpec(const nsACString & aSpec, nsIURIMutator** aMutator) override {
+      NS_ADDREF(*aMutator = this);
       return InitFromSpec(aSpec);
     }
 
     explicit Mutator() { }
   private:
     virtual ~Mutator() { }
 
     friend class nsMozIconURI;
--- a/modules/libjar/nsJARURI.h
+++ b/modules/libjar/nsJARURI.h
@@ -99,17 +99,17 @@ protected:
     nsCString        mCharsetHint;
 
 public:
     class Mutator
         : public nsIURIMutator
         , public BaseURIMutator<nsJARURI>
     {
         NS_DECL_ISUPPORTS
-        NS_FORWARD_SAFE_NSIURISETTERS(mURI)
+        NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
         NS_DEFINE_NSIMUTATOR_COMMON
 
         explicit Mutator() { }
     private:
         virtual ~Mutator() { }
 
         friend class nsJARURI;
     };
--- a/netwerk/base/nsIURIMutator.idl
+++ b/netwerk/base/nsIURIMutator.idl
@@ -1,16 +1,17 @@
 /* -*- 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 "nsISupports.idl"
 interface nsIURI;
 interface nsIObjectInputStream;
+interface nsIURIMutator;
 
 %{C++
 #include "nsStringGlue.h"
 
 #undef SetPort  // XXX Windows!
 
 namespace mozilla {
 class Encoding;
@@ -82,54 +83,96 @@ protected:
 // to avoid code duplication.
 #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) override                       \
-    { return InitFromSpec(aSpec); }
-
+  NS_IMETHOD SetSpec(const nsACString & aSpec, nsIURIMutator** aMutator) override \
+    { 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
 {
   /**
    * This setter is different from all other setters because it may be used to
    * initialize the object. We define it separately allowing mutator implementors
    * to define it separately, while the rest of the setters may be simply
    * forwarded to the mutable URI.
    */
-  void setSpec(in AUTF8String aSpec);
+  nsIURIMutator setSpec(in AUTF8String aSpec);
 };
 
+/**
+ * These methods allow the mutator to change various parts of the URI.
+ * They return the same nsIURIMutator so that we may chain setter operations:
+ * Example:
+ * let newURI = uri.mutate()
+ *                 .setSpec("http://example.com")
+ *                 .setQuery("hello")
+ *                 .finalize();
+ */
 [scriptable, builtinclass, uuid(5403a6ec-99d7-405e-8b45-9f805bbdfcef)]
 interface nsIURISetters : nsIURISetSpec
 {
-  void setScheme(in AUTF8String aScheme);
-  void setUserPass(in AUTF8String aUserPass);
-  void setUsername(in AUTF8String aUsername);
-  void setPassword(in AUTF8String aPassword);
-  void setHostPort(in AUTF8String aHostPort);
-  void setHostAndPort(in AUTF8String aHostAndPort);
-  void setHost(in AUTF8String aHost);
-  void setPort(in long aPort);
-  void setPathQueryRef(in AUTF8String aPathQueryRef);
-  void setRef(in AUTF8String aRef);
-  void setFilePath(in AUTF8String aFilePath);
-  void setQuery(in AUTF8String aQuery);
-  [noscript] void setQueryWithEncoding(in AUTF8String query, in Encoding encoding);
+  nsIURIMutator setScheme(in AUTF8String aScheme);
+  nsIURIMutator setUserPass(in AUTF8String aUserPass);
+  nsIURIMutator setUsername(in AUTF8String aUsername);
+  nsIURIMutator setPassword(in AUTF8String aPassword);
+  nsIURIMutator setHostPort(in AUTF8String aHostPort);
+  nsIURIMutator setHostAndPort(in AUTF8String aHostAndPort);
+  nsIURIMutator setHost(in AUTF8String aHost);
+  nsIURIMutator setPort(in long aPort);
+  nsIURIMutator setPathQueryRef(in AUTF8String aPathQueryRef);
+  nsIURIMutator setRef(in AUTF8String aRef);
+  nsIURIMutator setFilePath(in AUTF8String aFilePath);
+  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); }
+
+%}
+
 [scriptable, builtinclass, uuid(4d1f3103-1c44-4dcd-b717-5d22a697a7d9)]
 interface nsIURIMutator : nsIURISetters
 {
   /**
    * Initializes the URI by reading from the input stream.
    * The input stream must contain the serialization of the same object type.
    * See nsISerializable.
    */
--- a/netwerk/base/nsSimpleNestedURI.h
+++ b/netwerk/base/nsSimpleNestedURI.h
@@ -72,18 +72,18 @@ protected:
 
 
 public:
     class Mutator
         : public nsIURIMutator
         , public BaseURIMutator<nsSimpleNestedURI>
     {
         NS_DECL_ISUPPORTS
-        NS_FORWARD_SAFE_NSIURISETTERS(mURI)
         NS_DEFINE_NSIMUTATOR_COMMON
+        NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
 
         explicit Mutator() { }
     private:
         virtual ~Mutator() { }
 
         friend class nsSimpleNestedURI;
     };
 };
--- a/netwerk/base/nsSimpleURI.h
+++ b/netwerk/base/nsSimpleURI.h
@@ -113,17 +113,17 @@ protected:
 
 
 public:
     class Mutator
         : public nsIURIMutator
         , public BaseURIMutator<nsSimpleURI>
     {
         NS_DECL_ISUPPORTS
-        NS_FORWARD_SAFE_NSIURISETTERS(mURI)
+        NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
         NS_DEFINE_NSIMUTATOR_COMMON
 
         explicit Mutator() { }
     private:
         virtual ~Mutator() { }
 
         friend class nsSimpleURI;
     };
--- a/netwerk/base/nsStandardURL.h
+++ b/netwerk/base/nsStandardURL.h
@@ -313,17 +313,17 @@ public:
 #endif
 
 public:
     class Mutator
         : public nsIURIMutator
         , public BaseURIMutator<nsStandardURL>
     {
         NS_DECL_ISUPPORTS
-        NS_FORWARD_SAFE_NSIURISETTERS(mURI)
+        NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
         NS_DEFINE_NSIMUTATOR_COMMON
 
         explicit Mutator() { }
     private:
         virtual ~Mutator() { }
 
         friend class nsStandardURL;
     };
--- a/netwerk/protocol/about/nsAboutProtocolHandler.h
+++ b/netwerk/protocol/about/nsAboutProtocolHandler.h
@@ -87,17 +87,17 @@ protected:
     nsCOMPtr<nsIURI> mBaseURI;
 
 public:
     class Mutator
         : public nsIURIMutator
         , public BaseURIMutator<nsNestedAboutURI>
     {
         NS_DECL_ISUPPORTS
-        NS_FORWARD_SAFE_NSIURISETTERS(mURI)
+        NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
         NS_DEFINE_NSIMUTATOR_COMMON
 
         explicit Mutator() { }
     private:
         virtual ~Mutator() { }
 
         friend class nsNestedAboutURI;
     };
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_uri_mutator.js
@@ -0,0 +1,23 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 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/. */
+
+"use strict";
+Cu.import("resource://gre/modules/NetUtil.jsm");
+
+function standardMutator()
+{
+  return Cc['@mozilla.org/network/standard-url-mutator;1']
+           .createInstance(Ci.nsIURIMutator);
+}
+
+add_task(async function test_simple_setter_chaining() {
+  let uri = standardMutator()
+              .setSpec("http://example.com/")
+              .setQuery("hello")
+              .setRef("bla")
+              .setScheme("ftp")
+              .finalize();
+  equal(uri.spec, "ftp://example.com/?hello#bla");
+});
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -400,8 +400,9 @@ skip-if = os == "android"
 [test_channel_priority.js]
 [test_bug1312774_http1.js]
 [test_1351443-missing-NewChannel2.js]
 [test_bug1312782_http1.js]
 [test_bug1355539_http1.js]
 [test_bug1378385_http1.js]
 [test_tls_flags_separate_connections.js]
 [test_tls_flags.js]
+[test_uri_mutator.js]