Bug 1151899 - Add code to run both URL parsers at the same time; r=bagder,ted,valentin
authorValentin Gosu <valentin.gosu@gmail.com>
Tue, 08 Nov 2016 00:42:36 +0100
changeset 323136 79ec544204fc005bef2bfff1b51fbf0be4bcab3f
parent 323135 17436aa19280151da633776f8b229e0b18812185
child 323137 b9a918aca10c791c8cfedfa2d759b3505a44c666
push id30970
push usercbook@mozilla.com
push dateFri, 18 Nov 2016 15:49:14 +0000
treeherdermozilla-central@6186126f502b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbagder, ted, valentin
bugs1151899
milestone53.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 1151899 - Add code to run both URL parsers at the same time; r=bagder,ted,valentin MozReview-Commit-ID: Jd2RgPmdPrn
browser/confvars.sh
netwerk/base/RustURL.cpp
netwerk/base/RustURL.h
netwerk/base/moz.build
netwerk/base/nsStandardURL.cpp
netwerk/base/nsStandardURL.h
netwerk/base/rust-url-capi/src/lib.rs
old-configure.in
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -24,16 +24,21 @@ if test "$OS_ARCH" = "WINNT"; then
             "$MOZ_UPDATE_CHANNEL" = "release-dev"; then
       if ! test "$MOZ_DEBUG"; then
         MOZ_STUB_INSTALLER=1
       fi
     fi
   fi
 fi
 
+if test "$MOZ_UPDATE_CHANNEL" = "default" -o \
+        "$MOZ_UPDATE_CHANNEL" = "nightly"; then
+  MOZ_RUST_URLPARSE=1
+fi
+
 # Enable building ./signmar and running libmar signature tests
 MOZ_ENABLE_SIGNMAR=1
 
 MOZ_APP_VERSION=$FIREFOX_VERSION
 MOZ_APP_VERSION_DISPLAY=$FIREFOX_VERSION_DISPLAY
 MOZ_EXTENSIONS_DEFAULT=" gio"
 # MOZ_APP_DISPLAYNAME will be set by branding/configure.sh
 # MOZ_BRANDING_DIRECTORY is the default branding directory used when none is
@@ -50,15 +55,14 @@ MOZ_APP_ID={ec8030f7-c20a-464f-9b0e-13a3
 ACCEPTED_MAR_CHANNEL_IDS=firefox-mozilla-central
 # The MAR_CHANNEL_ID must not contain the following 3 characters: ",\t "
 MAR_CHANNEL_ID=firefox-mozilla-central
 MOZ_PROFILE_MIGRATOR=1
 MOZ_APP_STATIC_INI=1
 MOZ_WEBGL_CONFORMANT=1
 MOZ_JSDOWNLOADS=1
 MOZ_RUST_MP4PARSE=1
-MOZ_RUST_URLPARSE=1
 
 # Enable checking that add-ons are signed by the trusted root
 MOZ_ADDON_SIGNING=1
 
 # Include the DevTools client, not just the server (which is the default)
 MOZ_DEVTOOLS=all
--- a/netwerk/base/RustURL.cpp
+++ b/netwerk/base/RustURL.cpp
@@ -27,16 +27,17 @@ namespace mozilla {
 namespace net {
 
 NS_IMPL_ADDREF(RustURL)
 NS_IMPL_RELEASE(RustURL)
 
 NS_INTERFACE_MAP_BEGIN(RustURL)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStandardURL)
   NS_INTERFACE_MAP_ENTRY(nsIURI)
+  NS_INTERFACE_MAP_ENTRY(nsIURIWithQuery)
   NS_INTERFACE_MAP_ENTRY(nsIURL)
   // NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIFileURL, mSupportsFileURL)
   NS_INTERFACE_MAP_ENTRY(nsIStandardURL)
   // NS_INTERFACE_MAP_ENTRY(nsISerializable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   NS_INTERFACE_MAP_ENTRY(nsIMutable)
   // NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableURI)
   // NS_INTERFACE_MAP_ENTRY(nsISensitiveInfoHiddenURI)
--- a/netwerk/base/RustURL.h
+++ b/netwerk/base/RustURL.h
@@ -26,16 +26,17 @@ class RustURL
   , public nsISerializable
   , public nsIClassInfo
   , public nsISizeOf
   , public nsIIPCSerializableURI
   , public nsISensitiveInfoHiddenURI
 {
   NS_DECL_ISUPPORTS
   NS_DECL_NSIURI
+  NS_DECL_NSIURIWITHQUERY
   NS_DECL_NSIURL
   NS_DECL_NSIFILEURL
   NS_DECL_NSISTANDARDURL
   NS_DECL_NSISERIALIZABLE
   NS_DECL_NSICLASSINFO
   NS_DECL_NSIMUTABLE
   NS_DECL_NSIIPCSERIALIZABLEURI
   NS_DECL_NSISENSITIVEINFOHIDDENURI
--- a/netwerk/base/moz.build
+++ b/netwerk/base/moz.build
@@ -254,17 +254,17 @@ UNIFIED_SOURCES += [
     'RequestContextService.cpp',
     'SimpleBuffer.cpp',
     'StreamingProtocolService.cpp',
     'ThrottleQueue.cpp',
     'Tickler.cpp',
     'TLSServerSocket.cpp',
 ]
 
-if CONFIG['MOZ_RUST']:
+if CONFIG['MOZ_RUST'] and CONFIG['MOZ_RUST_URLPARSE']:
     EXPORTS.mozilla.net += [ 'RustURL.h' ]
     UNIFIED_SOURCES += [ 'RustURL.cpp' ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     SOURCES += [
         'nsURLHelperWin.cpp',
         'ShutdownLayer.cpp',
     ]
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -22,42 +22,114 @@
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/ipc/URIUtils.h"
 #include <algorithm>
 #include "mozilla/dom/EncodingUtils.h"
 #include "nsContentUtils.h"
 #include "prprf.h"
 #include "nsReadableUtils.h"
 
+
+//
+// setenv MOZ_LOG nsStandardURL:5
+//
+static LazyLogModule gStandardURLLog("nsStandardURL");
+
+// The Chromium code defines its own LOG macro which we don't want
+#undef LOG
+#define LOG(args)     MOZ_LOG(gStandardURLLog, LogLevel::Debug, args)
+#undef LOG_ENABLED
+#define LOG_ENABLED() MOZ_LOG_TEST(gStandardURLLog, LogLevel::Debug)
+
+#ifdef MOZ_RUST_URLPARSE
+
+#include "RustURL.h"
+
+// Fall back to CPP-parsed URLs if the Rust one doesn't match.
+#define MOZ_RUST_URLPARSE_FALLBACK
+
+#ifdef MOZ_RUST_URLPARSE_FALLBACK
+#define MOZ_RUST_URLPARSE_FALLBACK_MACRO(expr) expr
+#else
+#define MOZ_RUST_URLPARSE_FALLBACK_MACRO(expr)
+#endif
+
+#define CALL_RUST_SETTER(func, ...)  \
+do {                                 \
+    mRustURL->func(__VA_ARGS__);     \
+    nsAutoCString rustSpec;          \
+    mRustURL->GetSpec(rustSpec);     \
+    if (mSpec != rustSpec) {         \
+        LOG(("Spec diff detected after setter (%s): rust: %s standard-url: %s\n", \
+             #func, rustSpec.get(), mSpec.get())); \
+    }                                \
+} while (0)
+
+#define CALL_RUST_GETTER_STR(result, func, ...)  \
+do {                                             \
+    nsAutoCString backup(result);                \
+    mRustURL->func(__VA_ARGS__);                 \
+    if (backup != result) {                      \
+        LOG(("Diff detected calling getter (%s): rust: %s standard-url: %s\n", \
+             #func, result.BeginReading() , backup.BeginReading())); \
+        MOZ_RUST_URLPARSE_FALLBACK_MACRO(result = backup);          \
+    }                                            \
+} while (0)
+
+#define CALL_RUST_GETTER_INT(result, func, ...)  \
+do {                                             \
+    int32_t backup = *result;                    \
+    mRustURL->func(__VA_ARGS__);                 \
+    if (backup != *result) {                     \
+        LOG(("Diff detected calling getter (%s): rust: %d standard-url: %d\n", \
+             #func, *result , backup)); \
+        MOZ_RUST_URLPARSE_FALLBACK_MACRO(*result = backup);         \
+    }                                            \
+} while (0)
+
+#define COPY_RUST_MEMBER                \
+do {                                    \
+  RefPtr<RustURL> url = new RustURL();  \
+  nsAutoCString spec;                   \
+  GetSpec(spec);                        \
+  url->SetSpec(spec);                   \
+  mRustURL = url;                       \
+} while (0)
+
+#define CALL_RUST_SYNC  mRustURL->SetSpec(mSpec)
+#define CALL_SET_MUTABLE  mRustURL->SetMutable(value)
+#define CALL_RUST_INIT mRustURL->Init(urlType, defaultPort, spec, charset, baseURI)
+
+#else
+
+#define CALL_RUST_SETTER(func, ...)
+#define CALL_RUST_GETTER_STR(expected, func, ...)
+#define CALL_RUST_GETTER_INT(expected, func, ...)
+#define CALL_RUST_INIT
+#define CALL_RUST_SYNC
+#define CALL_SET_MUTABLE
+#define COPY_RUST_MEMBER
+
+#endif // MOZ_RUST_URLPARSE
+
 using mozilla::dom::EncodingUtils;
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace net {
 
 static NS_DEFINE_CID(kThisImplCID, NS_THIS_STANDARDURL_IMPL_CID);
 static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
 
 nsIIDNService *nsStandardURL::gIDN = nullptr;
 bool nsStandardURL::gInitialized = false;
 bool nsStandardURL::gEscapeUTF8 = true;
 bool nsStandardURL::gAlwaysEncodeInUTF8 = true;
 char nsStandardURL::gHostLimitDigits[] = { '/', '\\', '?', '#', 0 };
 
-//
-// setenv MOZ_LOG nsStandardURL:5
-//
-static LazyLogModule gStandardURLLog("nsStandardURL");
-
-// The Chromium code defines its own LOG macro which we don't want
-#undef LOG
-#define LOG(args)     MOZ_LOG(gStandardURLLog, LogLevel::Debug, args)
-#undef LOG_ENABLED
-#define LOG_ENABLED() MOZ_LOG_TEST(gStandardURLLog, LogLevel::Debug)
-
 //----------------------------------------------------------------------------
 
 #define ENSURE_MUTABLE() \
   PR_BEGIN_MACRO \
     if (!mMutable) { \
         NS_WARNING("attempt to modify an immutable nsStandardURL"); \
         return NS_ERROR_ABORT; \
     } \
@@ -272,16 +344,20 @@ nsStandardURL::nsStandardURL(bool aSuppo
     if (NS_IsMainThread()) {
         if (aTrackURL) {
             PR_APPEND_LINK(&mDebugCList, &gAllURLs);
         } else {
             PR_INIT_CLIST(&mDebugCList);
         }
     }
 #endif
+
+#ifdef MOZ_RUST_URLPARSE
+    mRustURL = new RustURL();
+#endif
 }
 
 nsStandardURL::~nsStandardURL()
 {
     LOG(("Destroying nsStandardURL @%p\n", this));
 
     if (mHostA) {
         free(mHostA);
@@ -1200,208 +1276,229 @@ NS_INTERFACE_MAP_END
 
 // result may contain unescaped UTF-8 characters
 NS_IMETHODIMP
 nsStandardURL::GetSpec(nsACString &result)
 {
     MOZ_ASSERT(mSpec.Length() <= (uint32_t) net_GetURLMaxLength(),
                "The spec should never be this long, we missed a check.");
     result = mSpec;
+    CALL_RUST_GETTER_STR(result, GetSpec, result);
     return NS_OK;
 }
 
 // result may contain unescaped UTF-8 characters
 NS_IMETHODIMP
 nsStandardURL::GetSensitiveInfoHiddenSpec(nsACString &result)
 {
     result = mSpec;
     if (mPassword.mLen >= 0) {
       result.Replace(mPassword.mPos, mPassword.mLen, "****");
     }
+    CALL_RUST_GETTER_STR(result, GetSensitiveInfoHiddenSpec, result);
     return NS_OK;
 }
 
 // result may contain unescaped UTF-8 characters
 NS_IMETHODIMP
 nsStandardURL::GetSpecIgnoringRef(nsACString &result)
 {
     // URI without ref is 0 to one char before ref
     if (mRef.mLen >= 0) {
         URLSegment noRef(0, mRef.mPos - 1);
 
         result = Segment(noRef);
     } else {
         result = mSpec;
     }
+    CALL_RUST_GETTER_STR(result, GetSpecIgnoringRef, result);
     return NS_OK;
 }
 
 // result may contain unescaped UTF-8 characters
 NS_IMETHODIMP
 nsStandardURL::GetPrePath(nsACString &result)
 {
     result = Prepath();
+    CALL_RUST_GETTER_STR(result, GetPrePath, result);
     return NS_OK;
 }
 
 // result is strictly US-ASCII
 NS_IMETHODIMP
 nsStandardURL::GetScheme(nsACString &result)
 {
     result = Scheme();
+    CALL_RUST_GETTER_STR(result, GetScheme, result);
     return NS_OK;
 }
 
 // result may contain unescaped UTF-8 characters
 NS_IMETHODIMP
 nsStandardURL::GetUserPass(nsACString &result)
 {
     result = Userpass();
+    CALL_RUST_GETTER_STR(result, GetUserPass, result);
     return NS_OK;
 }
 
 // result may contain unescaped UTF-8 characters
 NS_IMETHODIMP
 nsStandardURL::GetUsername(nsACString &result)
 {
     result = Username();
+    CALL_RUST_GETTER_STR(result, GetUsername, result);
     return NS_OK;
 }
 
 // result may contain unescaped UTF-8 characters
 NS_IMETHODIMP
 nsStandardURL::GetPassword(nsACString &result)
 {
     result = Password();
+    CALL_RUST_GETTER_STR(result, GetPassword, result);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::GetHostPort(nsACString &result)
 {
     result = Hostport();
+    CALL_RUST_GETTER_STR(result, GetHostPort, result);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::GetHost(nsACString &result)
 {
     result = Host();
+    CALL_RUST_GETTER_STR(result, GetHost, result);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::GetPort(int32_t *result)
 {
     // should never be more than 16 bit
     MOZ_ASSERT(mPort <= std::numeric_limits<uint16_t>::max());
     *result = mPort;
+    CALL_RUST_GETTER_INT(result, GetPort, result);
     return NS_OK;
 }
 
 // result may contain unescaped UTF-8 characters
 NS_IMETHODIMP
 nsStandardURL::GetPath(nsACString &result)
 {
     result = Path();
+    CALL_RUST_GETTER_STR(result, GetPath, result);
     return NS_OK;
 }
 
 // result is ASCII
 NS_IMETHODIMP
 nsStandardURL::GetAsciiSpec(nsACString &result)
 {
     if (mSpecEncoding == eEncoding_Unknown) {
         if (IsASCII(mSpec))
             mSpecEncoding = eEncoding_ASCII;
         else
             mSpecEncoding = eEncoding_UTF8;
     }
 
     if (mSpecEncoding == eEncoding_ASCII) {
         result = mSpec;
+        CALL_RUST_GETTER_STR(result, GetAsciiSpec, result);
         return NS_OK;
     }
 
     // try to guess the capacity required for result...
     result.SetCapacity(mSpec.Length() + std::min<uint32_t>(32, mSpec.Length()/10));
 
     result = Substring(mSpec, 0, mScheme.mLen + 3);
 
     NS_EscapeURL(Userpass(true), esc_OnlyNonASCII | esc_AlwaysCopy, result);
 
     // get the hostport
     nsAutoCString hostport;
     MOZ_ALWAYS_SUCCEEDS(GetAsciiHostPort(hostport));
     result += hostport;
 
     NS_EscapeURL(Path(), esc_OnlyNonASCII | esc_AlwaysCopy, result);
+    CALL_RUST_GETTER_STR(result, GetAsciiSpec, result);
     return NS_OK;
 }
 
 // result is ASCII
 NS_IMETHODIMP
 nsStandardURL::GetAsciiHostPort(nsACString &result)
 {
     if (mHostEncoding == eEncoding_ASCII) {
         result = Hostport();
+        CALL_RUST_GETTER_STR(result, GetAsciiHostPort, result);
         return NS_OK;
     }
 
     MOZ_ALWAYS_SUCCEEDS(GetAsciiHost(result));
 
     // As our mHostEncoding is not eEncoding_ASCII, we know that
     // the our host is not ipv6, and we can avoid looking at it.
     MOZ_ASSERT(result.FindChar(':') == -1, "The host must not be ipv6");
 
     // hostport = "hostA" + ":port"
     uint32_t pos = mHost.mPos + mHost.mLen;
     if (pos < mPath.mPos)
         result += Substring(mSpec, pos, mPath.mPos - pos);
 
+    CALL_RUST_GETTER_STR(result, GetAsciiHostPort, result);
     return NS_OK;
 }
 
 // result is ASCII
 NS_IMETHODIMP
 nsStandardURL::GetAsciiHost(nsACString &result)
 {
     if (mHostEncoding == eEncoding_ASCII) {
         result = Host();
+        CALL_RUST_GETTER_STR(result, GetAsciiHost, result);
         return NS_OK;
     }
 
     // perhaps we have it cached...
     if (mHostA) {
         result = mHostA;
+        CALL_RUST_GETTER_STR(result, GetAsciiHost, result);
         return NS_OK;
     }
 
     if (gIDN) {
         nsresult rv;
         rv = gIDN->ConvertUTF8toACE(Host(), result);
+        CALL_RUST_GETTER_STR(result, GetAsciiHost, result);
         if (NS_SUCCEEDED(rv)) {
             mHostA = ToNewCString(result);
             return NS_OK;
         }
         NS_WARNING("nsIDNService::ConvertUTF8toACE failed");
     }
 
     // something went wrong... guess all we can do is URL escape :-/
     NS_EscapeURL(Host(), esc_OnlyNonASCII | esc_AlwaysCopy, result);
+    CALL_RUST_GETTER_STR(result, GetAsciiHost, result);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::GetOriginCharset(nsACString &result)
 {
     if (mOriginCharset.IsEmpty())
         result.AssignLiteral("UTF-8");
     else
         result = mOriginCharset;
+    CALL_RUST_GETTER_STR(result, GetOriginCharset, result);
     return NS_OK;
 }
 
 static bool
 IsSpecialProtocol(const nsACString &input)
 {
     nsACString::const_iterator start, end;
     input.BeginReading(start);
@@ -1496,16 +1593,18 @@ nsStandardURL::SetSpec(const nsACString 
         LOG((" path      = (%u,%d)\n", mPath.mPos,      mPath.mLen));
         LOG((" filepath  = (%u,%d)\n", mFilepath.mPos,  mFilepath.mLen));
         LOG((" directory = (%u,%d)\n", mDirectory.mPos, mDirectory.mLen));
         LOG((" basename  = (%u,%d)\n", mBasename.mPos,  mBasename.mLen));
         LOG((" extension = (%u,%d)\n", mExtension.mPos, mExtension.mLen));
         LOG((" query     = (%u,%d)\n", mQuery.mPos,     mQuery.mLen));
         LOG((" ref       = (%u,%d)\n", mRef.mPos,       mRef.mLen));
     }
+
+    CALL_RUST_SETTER(SetSpec, input);
     return rv;
 }
 
 NS_IMETHODIMP
 nsStandardURL::SetScheme(const nsACString &input)
 {
     ENSURE_MUTABLE();
 
@@ -1540,16 +1639,17 @@ nsStandardURL::SetScheme(const nsACStrin
         ShiftFromAuthority(shift);
     }
 
     // ensure new scheme is lowercase
     //
     // XXX the string code unfortunately doesn't provide a ToLowerCase
     //     that operates on a substring.
     net_ToLowerCase((char *) mSpec.get(), mScheme.mLen);
+    CALL_RUST_SETTER(SetScheme, input);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::SetUserPass(const nsACString &input)
 {
     ENSURE_MUTABLE();
 
@@ -1581,16 +1681,18 @@ nsStandardURL::SetUserPass(const nsACStr
                 mUsername.mLen += (mPassword.mLen + 1);
             mUsername.mLen++;
             mSpec.Cut(mUsername.mPos, mUsername.mLen);
             mAuthority.mLen -= mUsername.mLen;
             ShiftFromHost(-mUsername.mLen);
             mUsername.mLen = -1;
             mPassword.mLen = -1;
         }
+
+        CALL_RUST_SETTER(SetUserPass, input);
         return NS_OK;
     }
 
     NS_ASSERTION(mHost.mLen >= 0, "uninitialized");
 
     nsresult rv;
     uint32_t usernamePos, passwordPos;
     int32_t usernameLen, passwordLen;
@@ -1645,16 +1747,18 @@ nsStandardURL::SetUserPass(const nsACStr
         ShiftFromHost(shift);
         mAuthority.mLen += shift;
     }
     // update positions and lengths
     mUsername.mLen = usernameLen;
     mPassword.mLen = passwordLen;
     if (passwordLen)
         mPassword.mPos = mUsername.mPos + mUsername.mLen + 1;
+
+    CALL_RUST_SETTER(SetUserPass, input);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::SetUsername(const nsACString &input)
 {
     ENSURE_MUTABLE();
 
@@ -1694,16 +1798,18 @@ nsStandardURL::SetUsername(const nsACStr
     else
         shift = ReplaceSegment(mUsername.mPos, mUsername.mLen, escUsername);
 
     if (shift) {
         mUsername.mLen = escUsername.Length();
         mAuthority.mLen += shift;
         ShiftFromPassword(shift);
     }
+
+    CALL_RUST_SETTER(SetUsername, input);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::SetPassword(const nsACString &input)
 {
     ENSURE_MUTABLE();
 
@@ -1731,16 +1837,17 @@ nsStandardURL::SetPassword(const nsACStr
     if (password.IsEmpty()) {
         if (mPassword.mLen >= 0) {
             // cut(":password")
             mSpec.Cut(mPassword.mPos - 1, mPassword.mLen + 1);
             ShiftFromHost(-(mPassword.mLen + 1));
             mAuthority.mLen -= (mPassword.mLen + 1);
             mPassword.mLen = -1;
         }
+        CALL_RUST_SETTER(SetPassword, input);
         return NS_OK;
     }
 
     // escape password if necessary
     nsAutoCString buf;
     GET_SEGMENT_ENCODER(encoder);
     const nsACString &escPassword =
         encoder.EncodeSegment(password, esc_Password, buf);
@@ -1755,16 +1862,17 @@ nsStandardURL::SetPassword(const nsACStr
     else
         shift = ReplaceSegment(mPassword.mPos, mPassword.mLen, escPassword);
 
     if (shift) {
         mPassword.mLen = escPassword.Length();
         mAuthority.mLen += shift;
         ShiftFromHost(shift);
     }
+    CALL_RUST_SETTER(SetPassword, input);
     return NS_OK;
 }
 
 void
 nsStandardURL::FindHostLimit(nsACString::const_iterator& aStart,
                              nsACString::const_iterator& aEnd)
 {
   for (int32_t i = 0; gHostLimitDigits[i]; ++i) {
@@ -1838,29 +1946,30 @@ nsStandardURL::SetHostPort(const nsACStr
                 // Failure parsing port number
                 return NS_ERROR_MALFORMED_URI;
             }
         } else {
             // port number is missing
             return NS_ERROR_MALFORMED_URI;
         }
     }
-
+    CALL_RUST_SETTER(SetHostPort, aValue);
     return NS_OK;
 }
 
 // This function is different than SetHostPort in that the port number will be
 // reset as well if aValue parameter does not contain a port port number.
 NS_IMETHODIMP
 nsStandardURL::SetHostAndPort(const nsACString &aValue)
 {
   // Reset the port and than call SetHostPort. SetHostPort does not reset
   // the port number.
   nsresult rv = SetPort(-1);
   NS_ENSURE_SUCCESS(rv, rv);
+  CALL_RUST_SETTER(SetHostAndPort, aValue);
   return SetHostPort(aValue);
 }
 
 NS_IMETHODIMP
 nsStandardURL::SetHost(const nsACString &input)
 {
     ENSURE_MUTABLE();
 
@@ -1952,17 +2061,17 @@ nsStandardURL::SetHost(const nsACString 
     if (shift) {
         mHost.mLen = len;
         mAuthority.mLen += shift;
         ShiftFromPath(shift);
     }
 
     // Now canonicalize the host to lowercase
     net_ToLowerCase(mSpec.BeginWriting() + mHost.mPos, mHost.mLen);
-
+    CALL_RUST_SETTER(SetHost, input);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::SetPort(int32_t port)
 {
     ENSURE_MUTABLE();
 
@@ -1984,16 +2093,17 @@ nsStandardURL::SetPort(int32_t port)
     InvalidateCache();
     if (port == mDefaultPort) {
       port = -1;
     }
 
     ReplacePortInSpec(port);
 
     mPort = port;
+    CALL_RUST_SETTER(SetPort, port);
     return NS_OK;
 }
 
 /**
  * Replaces the existing port in mSpec with aNewPort.
  *
  * The caller is responsible for:
  *  - Calling InvalidateCache (since our mSpec is changing).
@@ -2062,16 +2172,17 @@ nsStandardURL::SetPath(const nsACString 
         mDirectory.mLen = 1;
         mFilepath.mLen = 1;
         // these are no longer defined
         mBasename.mLen = -1;
         mExtension.mLen = -1;
         mQuery.mLen = -1;
         mRef.mLen = -1;
     }
+    CALL_RUST_SETTER(SetPath, input);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::Equals(nsIURI *unknownOther, bool *result)
 {
     return EqualsInternal(unknownOther, eHonorRef, result);
 }
@@ -2247,16 +2358,17 @@ nsresult nsStandardURL::CopyMembers(nsSt
     mRef = source->mRef;
     mOriginCharset = source->mOriginCharset;
     mURLType = source->mURLType;
     mParser = source->mParser;
     mMutable = true;
     mSupportsFileURL = source->mSupportsFileURL;
     mHostEncoding = source->mHostEncoding;
 
+    COPY_RUST_MEMBER;
     if (copyCached) {
         mFile = source->mFile;
         mHostA = source->mHostA ? strdup(source->mHostA) : nullptr;
         mSpecEncoding = source->mSpecEncoding;
     } else {
         // The same state as after calling InvalidateCache()
         mFile = nullptr;
         mHostA = nullptr;
@@ -2264,16 +2376,17 @@ nsresult nsStandardURL::CopyMembers(nsSt
     }
 
     if (refHandlingMode == eIgnoreRef) {
         SetRef(EmptyCString());
     } else if (refHandlingMode == eReplaceRef) {
         SetRef(newRef);
     }
 
+
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::Resolve(const nsACString &in, nsACString &out)
 {
     const nsPromiseFlatCString &flat = PromiseFlatCString(in);
     // filter out unexpected chars "\r\n\t" if necessary
@@ -2768,16 +2881,17 @@ nsStandardURL::SetQuery(const nsACString
         if (mQuery.mLen >= 0) {
             // remove query and leading '?'
             mSpec.Cut(mQuery.mPos - 1, mQuery.mLen + 1);
             ShiftFromRef(-(mQuery.mLen + 1));
             mPath.mLen -= (mQuery.mLen + 1);
             mQuery.mPos = 0;
             mQuery.mLen = -1;
         }
+        CALL_RUST_SETTER(SetQuery, input);
         return NS_OK;
     }
 
     int32_t queryLen = flat.Length();
     if (query[0] == '?') {
         query++;
         queryLen--;
     }
@@ -2808,16 +2922,17 @@ nsStandardURL::SetQuery(const nsACString
 
     int32_t shift = ReplaceSegment(mQuery.mPos, mQuery.mLen, query, queryLen);
 
     if (shift) {
         mQuery.mLen = queryLen;
         mPath.mLen += shift;
         ShiftFromRef(shift);
     }
+    CALL_RUST_SETTER(SetQuery, input);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::SetRef(const nsACString &input)
 {
     ENSURE_MUTABLE();
 
@@ -2839,16 +2954,17 @@ nsStandardURL::SetRef(const nsACString &
         // remove existing ref
         if (mRef.mLen >= 0) {
             // remove ref and leading '#'
             mSpec.Cut(mRef.mPos - 1, mRef.mLen + 1);
             mPath.mLen -= (mRef.mLen + 1);
             mRef.mPos = 0;
             mRef.mLen = -1;
         }
+        CALL_RUST_SETTER(SetRef, input);
         return NS_OK;
     }
 
     int32_t refLen = flat.Length();
     if (ref[0] == '#') {
         ref++;
         refLen--;
     }
@@ -2873,16 +2989,17 @@ nsStandardURL::SetRef(const nsACString &
             ref = buf.get();
             refLen = buf.Length();
         }
     }
 
     int32_t shift = ReplaceSegment(mRef.mPos, mRef.mLen, ref, refLen);
     mPath.mLen += shift;
     mRef.mLen = refLen;
+    CALL_RUST_SETTER(SetRef, input);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::SetDirectory(const nsACString &input)
 {
     NS_NOTYETIMPLEMENTED("");
     return NS_ERROR_NOT_IMPLEMENTED;
@@ -3152,16 +3269,18 @@ nsStandardURL::Init(uint32_t urlType,
     if (charset != nullptr && *charset != '\0' && !IsUTFCharset(charset)) {
         mOriginCharset = charset;
     }
 
     if (baseURI && net_IsAbsoluteURL(spec)) {
         baseURI = nullptr;
     }
 
+    CALL_RUST_INIT;
+
     if (!baseURI)
         return SetSpec(spec);
 
     nsAutoCString buf;
     nsresult rv = baseURI->Resolve(spec, buf);
     if (NS_FAILED(rv)) return rv;
 
     return SetSpec(buf);
@@ -3199,16 +3318,17 @@ nsStandardURL::GetMutable(bool *value)
 }
 
 NS_IMETHODIMP
 nsStandardURL::SetMutable(bool value)
 {
     NS_ENSURE_ARG(mMutable || !value);
 
     mMutable = value;
+    CALL_SET_MUTABLE;
     return NS_OK;
 }
 
 //----------------------------------------------------------------------------
 // nsStandardURL::nsISerializable
 //----------------------------------------------------------------------------
 
 NS_IMETHODIMP
@@ -3318,16 +3438,17 @@ nsStandardURL::Read(nsIObjectInputStream
         // query and ref already.  Bump the mFilePath and 
         // directory/basename/extension components to include this.
         mFilepath.Merge(mSpec,  ';', old_param);
         mDirectory.Merge(mSpec, ';', old_param);
         mBasename.Merge(mSpec,  ';', old_param);
         mExtension.Merge(mSpec, ';', old_param);
     }
     
+    CALL_RUST_SYNC;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::Write(nsIObjectOutputStream *stream)
 {
     MOZ_ASSERT(mSpec.Length() <= (uint32_t) net_GetURLMaxLength(),
                "The spec should never be this long, we missed a check.");
@@ -3508,16 +3629,18 @@ nsStandardURL::Deserialize(const URIPara
     mExtension = FromIPCSegment(params.extension());
     mQuery = FromIPCSegment(params.query());
     mRef = FromIPCSegment(params.ref());
     mOriginCharset = params.originCharset();
     mMutable = params.isMutable();
     mSupportsFileURL = params.supportsFileURL();
     mHostEncoding = params.hostEncoding();
 
+    CALL_RUST_SYNC;
+
     // mSpecEncoding and mHostA are just caches that can be recovered as needed.
     return true;
 }
 
 //----------------------------------------------------------------------------
 // nsStandardURL::nsIClassInfo
 //----------------------------------------------------------------------------
 
--- a/netwerk/base/nsStandardURL.h
+++ b/netwerk/base/nsStandardURL.h
@@ -16,16 +16,17 @@
 #include "nsURLHelper.h"
 #include "nsIClassInfo.h"
 #include "nsISizeOf.h"
 #include "prclist.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReporting.h"
 #include "nsIIPCSerializableURI.h"
 #include "nsISensitiveInfoHiddenURI.h"
+#include "RustURL.h"
 
 #ifdef NS_BUILD_REFCNT_LOGGING
 #define DEBUG_DUMP_URLS_AT_SHUTDOWN
 #endif
 
 class nsIBinaryInputStream;
 class nsIBinaryOutputStream;
 class nsIIDNService;
@@ -305,16 +306,20 @@ private:
     static bool                         gAlwaysEncodeInUTF8;
     static bool                         gEncodeQueryInUTF8;
 
 public:
 #ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
     PRCList mDebugCList;
     void PrintSpec() const { printf("  %s\n", mSpec.get()); }
 #endif
+
+#ifdef MOZ_RUST_URLPARSE
+    RefPtr<RustURL>                    mRustURL;
+#endif
 };
 
 #define NS_THIS_STANDARDURL_IMPL_CID                 \
 { /* b8e3e97b-1ccd-4b45-af5a-79596770f5d7 */         \
     0xb8e3e97b,                                      \
     0x1ccd,                                          \
     0x4b45,                                          \
     {0xaf, 0x5a, 0x79, 0x59, 0x67, 0x70, 0xf5, 0xd7} \
--- a/netwerk/base/rust-url-capi/src/lib.rs
+++ b/netwerk/base/rust-url-capi/src/lib.rs
@@ -1,14 +1,14 @@
 /* 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/. */
 
 extern crate url;
-use url::{Url, ParseError, ParseOptions};
+use url::{Url, ParseError, ParseOptions, Position};
 use url::quirks;
 extern crate libc;
 use libc::size_t;
 
 
 use std::mem;
 use std::str;
 
@@ -139,17 +139,17 @@ pub unsafe extern "C" fn rusturl_get_por
 pub unsafe extern "C" fn rusturl_get_path(urlptr: rusturl_ptr, cont: *mut libc::c_void) -> i32 {
   if urlptr.is_null() {
     return NSError::InvalidArg.error_code();
   }
   let url: &Url = mem::transmute(urlptr);
   if url.cannot_be_a_base() {
       cont.set_size(0)
   } else {
-      cont.assign(url.path())
+      cont.assign(&url[Position::BeforePath..])
   }
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn rusturl_get_query(urlptr: rusturl_ptr, cont: *mut libc::c_void) -> i32 {
   if urlptr.is_null() {
     return NSError::InvalidArg.error_code();
   }
--- a/old-configure.in
+++ b/old-configure.in
@@ -2437,16 +2437,17 @@ fi
 
 # Propagate feature switches for code written in rust from confvars.sh
 if test -n "$MOZ_RUST"; then
     if test -n "$MOZ_RUST_MP4PARSE"; then
         AC_DEFINE(MOZ_RUST_MP4PARSE)
     fi
     if test -n "$MOZ_RUST_URLPARSE"; then
         AC_DEFINE(MOZ_RUST_URLPARSE)
+        AC_SUBST(MOZ_RUST_URLPARSE)
     fi
 fi
 
 AC_SUBST(MOZ_PHOENIX)
 AC_SUBST(MOZ_XULRUNNER)
 AC_SUBST(MOZ_B2G)
 AC_SUBST(MOZ_MULET)
 AC_SUBST(MOZ_B2G_VERSION)