Bug 1322874 - Get rid of nsIURI.originCharset. r=valentin.gosu
authorMasatoshi Kimura <VYV03354@nifty.ne.jp>
Wed, 02 Aug 2017 20:43:30 +0900
changeset 422138 8ff32bdb356daedca9e75d7f712aef7a05c60167
parent 422137 7b9d0ff207eb0d4723733676b1fbe05d68516b7e
child 422139 b5e38bafb4edb79bf627f8e301accb9d901f31b1
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvalentin
bugs1322874, 817374
milestone57.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 1322874 - Get rid of nsIURI.originCharset. r=valentin.gosu nsIURI.originCharset had two use cases: 1) Dealing with the spec-incompliant feature of escapes in the hash (reference) part of the URL. 2) For UI display of non-UTF-8 URLs. For hash part handling, we use the document charset instead. For pretty display of query strings on legacy-encoded pages, we no longer care to them (see bug 817374 comment 18). Also, the URL Standard has no concept of "origin charset". This patch removes nsIURI.originCharset for reducing complexity and spec compliance. MozReview-Commit-ID: 3tHd0VCWSqF
browser/base/content/content.js
browser/base/content/pageinfo/pageInfo.js
browser/base/content/tab-content.js
caps/NullPrincipalURI.cpp
chrome/RegistryMessageUtils.h
chrome/nsChromeRegistryChrome.cpp
chrome/nsChromeRegistryContent.cpp
docshell/base/nsDefaultURIFixup.cpp
docshell/base/nsDocShell.cpp
dom/base/Link.cpp
dom/base/Location.cpp
dom/base/nsReferencedElement.cpp
dom/html/MediaDocument.cpp
image/decoders/icon/nsIconURI.cpp
ipc/glue/URIParams.ipdlh
modules/libjar/nsJARURI.cpp
netwerk/base/RustURL.cpp
netwerk/base/RustURL.h
netwerk/base/nsIURI.idl
netwerk/base/nsNetUtil.cpp
netwerk/base/nsSimpleURI.cpp
netwerk/base/nsStandardURL.cpp
netwerk/base/nsStandardURL.h
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/res/SubstitutingProtocolHandler.cpp
netwerk/streamconv/converters/nsIndexedToHTML.cpp
toolkit/content/contentAreaUtils.js
toolkit/modules/BrowserUtils.jsm
toolkit/modules/sessionstore/SessionHistory.jsm
uriloader/exthandler/nsExternalHelperAppService.cpp
uriloader/exthandler/win/nsMIMEInfoWin.cpp
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -1205,17 +1205,16 @@ var PageInfoListener = {
     docInfo.compatMode = document.compatMode;
     docInfo.contentType = document.contentType;
     docInfo.characterSet = document.characterSet;
     docInfo.lastModified = document.lastModified;
     docInfo.principal = document.nodePrincipal;
 
     let documentURIObject = {};
     documentURIObject.spec = document.documentURIObject.spec;
-    documentURIObject.originCharset = document.documentURIObject.originCharset;
     docInfo.documentURIObject = documentURIObject;
 
     docInfo.isContentWindowPrivate = PrivateBrowsingUtils.isContentWindowPrivate(content);
 
     return docInfo;
   },
 
   getFeedsInfo(document, strings) {
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -357,18 +357,17 @@ function loadPageInfo(frameOuterWindowID
   let pageInfoData;
 
   // Get initial pageInfoData needed to display the general, feeds, permission and security tabs.
   mm.addMessageListener("PageInfo:data", function onmessage(message) {
     mm.removeMessageListener("PageInfo:data", onmessage);
     pageInfoData = message.data;
     let docInfo = pageInfoData.docInfo;
     let windowInfo = pageInfoData.windowInfo;
-    let uri = makeURI(docInfo.documentURIObject.spec,
-                      docInfo.documentURIObject.originCharset);
+    let uri = makeURI(docInfo.documentURIObject.spec);
     let principal = docInfo.principal;
     gDocInfo = docInfo;
 
     gImageElement = pageInfoData.imageInfo;
 
     var titleFormat = windowInfo.isTopWindow ? "pageInfo.page.title"
                                              : "pageInfo.frame.title";
     document.title = gBundle.getFormattedString(titleFormat, [docInfo.location]);
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -974,17 +974,16 @@ var RefreshBlocker = {
   onRefreshAttempted(aWebProgress, aURI, aDelay, aSameURI) {
     let win = aWebProgress.DOMWindow;
     let outerWindowID = win.QueryInterface(Ci.nsIInterfaceRequestor)
                            .getInterface(Ci.nsIDOMWindowUtils)
                            .outerWindowID;
 
     let data = {
       URI: aURI.spec,
-      originCharset: aURI.originCharset,
       delay: aDelay,
       sameURI: aSameURI,
       outerWindowID,
     };
 
     if (this.blockedWindows.has(win)) {
       // onLocationChange must have fired before, so we can tell the
       // parent to show the notification.
@@ -1002,17 +1001,17 @@ var RefreshBlocker = {
     let data = message.data;
 
     if (message.name == "RefreshBlocker:Refresh") {
       let win = Services.wm.getOuterWindowWithId(data.outerWindowID);
       let refreshURI = win.QueryInterface(Ci.nsIInterfaceRequestor)
                           .getInterface(Ci.nsIDocShell)
                           .QueryInterface(Ci.nsIRefreshURI);
 
-      let URI = Services.io.newURI(data.URI, data.originCharset);
+      let URI = Services.io.newURI(data.URI);
 
       refreshURI.forceRefreshURI(URI, data.delay, true);
     }
   },
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener2,
                                          Ci.nsIWebProgressListener,
                                          Ci.nsISupportsWeakReference,
--- a/caps/NullPrincipalURI.cpp
+++ b/caps/NullPrincipalURI.cpp
@@ -131,23 +131,16 @@ NullPrincipalURI::SetHostPort(const nsAC
 
 NS_IMETHODIMP
 NullPrincipalURI::SetHostAndPort(const nsACString& aHost)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-NullPrincipalURI::GetOriginCharset(nsACString& _charset)
-{
-  _charset.Truncate();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 NullPrincipalURI::GetPassword(nsACString& _password)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 NullPrincipalURI::SetPassword(const nsACString& aPassword)
 {
@@ -189,16 +182,23 @@ NullPrincipalURI::GetQuery(nsACString& a
 
 NS_IMETHODIMP
 NullPrincipalURI::SetQuery(const nsACString& aQuery)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
+NullPrincipalURI::SetQueryWithEncoding(const nsACString& aQuery,
+                                       const Encoding* aEncoding)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 NullPrincipalURI::GetRef(nsACString& _ref)
 {
   _ref.Truncate();
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 NullPrincipalURI::SetRef(const nsACString& aRef)
--- a/chrome/RegistryMessageUtils.h
+++ b/chrome/RegistryMessageUtils.h
@@ -7,22 +7,20 @@
 #define mozilla_RegistryMessageUtils_h
 
 #include "ipc/IPCMessageUtils.h"
 #include "nsString.h"
 
 struct SerializedURI
 {
   nsCString spec;
-  nsCString charset;
 
   bool operator ==(const SerializedURI& rhs) const
   {
-      return spec.Equals(rhs.spec) &&
-             charset.Equals(rhs.charset);
+      return spec.Equals(rhs.spec);
   }
 };
 
 struct ChromePackage
 {
   nsCString package;
   SerializedURI contentBaseURI;
   SerializedURI localeBaseURI;
@@ -70,26 +68,23 @@ namespace IPC {
 template<>
 struct ParamTraits<SerializedURI>
 {
   typedef SerializedURI paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.spec);
-    WriteParam(aMsg, aParam.charset);
   }
 
   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
-    nsCString spec, charset;
-    if (ReadParam(aMsg, aIter, &spec) &&
-        ReadParam(aMsg, aIter, &charset)) {
+    nsCString spec;
+    if (ReadParam(aMsg, aIter, &spec)) {
       aResult->spec = spec;
-      aResult->charset = charset;
       return true;
     }
     return false;
   }
 };
 
 template <>
 struct ParamTraits<ChromePackage>
--- a/chrome/nsChromeRegistryChrome.cpp
+++ b/chrome/nsChromeRegistryChrome.cpp
@@ -324,17 +324,16 @@ nsChromeRegistryChrome::CheckForNewChrom
 static void
 SerializeURI(nsIURI* aURI,
              SerializedURI& aSerializedURI)
 {
   if (!aURI)
     return;
 
   aURI->GetSpec(aSerializedURI.spec);
-  aURI->GetOriginCharset(aSerializedURI.charset);
 }
 
 void
 nsChromeRegistryChrome::SendRegisteredChrome(
     mozilla::dom::PContentParent* aParent)
 {
   InfallibleTArray<ChromePackage> packages;
   InfallibleTArray<SubstitutionMapping> resources;
--- a/chrome/nsChromeRegistryContent.cpp
+++ b/chrome/nsChromeRegistryContent.cpp
@@ -56,34 +56,31 @@ nsChromeRegistryContent::RegisterPackage
   if (!io)
     return;
 
   nsCOMPtr<nsIURI> content, locale, skin;
 
   if (aPackage.contentBaseURI.spec.Length()) {
     nsresult rv = NS_NewURI(getter_AddRefs(content),
                             aPackage.contentBaseURI.spec,
-                            aPackage.contentBaseURI.charset.get(),
-                            nullptr, io);
+                            nullptr, nullptr, io);
     if (NS_FAILED(rv))
       return;
   }
   if (aPackage.localeBaseURI.spec.Length()) {
     nsresult rv = NS_NewURI(getter_AddRefs(locale),
                             aPackage.localeBaseURI.spec,
-                            aPackage.localeBaseURI.charset.get(),
-                            nullptr, io);
+                            nullptr, nullptr, io);
     if (NS_FAILED(rv))
       return;
   }
   if (aPackage.skinBaseURI.spec.Length()) {
     nsresult rv = NS_NewURI(getter_AddRefs(skin),
                             aPackage.skinBaseURI.spec,
-                            aPackage.skinBaseURI.charset.get(),
-                            nullptr, io);
+                            nullptr, nullptr, io);
     if (NS_FAILED(rv))
       return;
   }
 
   PackageEntry* entry = new PackageEntry;
   entry->flags = aPackage.flags;
   entry->contentBaseURI = content;
   entry->localeBaseURI = locale;
@@ -107,18 +104,17 @@ nsChromeRegistryContent::RegisterSubstit
   nsCOMPtr<nsISubstitutingProtocolHandler> sph (do_QueryInterface(ph));
   if (!sph)
     return;
 
   nsCOMPtr<nsIURI> resolvedURI;
   if (aSubstitution.resolvedURI.spec.Length()) {
     rv = NS_NewURI(getter_AddRefs(resolvedURI),
                    aSubstitution.resolvedURI.spec,
-                   aSubstitution.resolvedURI.charset.get(),
-                   nullptr, io);
+                   nullptr, nullptr, io);
     if (NS_FAILED(rv))
       return;
   }
 
   rv = sph->SetSubstitution(aSubstitution.path, resolvedURI);
   if (NS_FAILED(rv))
     return;
 }
@@ -128,23 +124,22 @@ nsChromeRegistryContent::RegisterOverrid
 {
   nsCOMPtr<nsIIOService> io (do_GetIOService());
   if (!io)
     return;
 
   nsCOMPtr<nsIURI> chromeURI, overrideURI;
   nsresult rv = NS_NewURI(getter_AddRefs(chromeURI),
                           aOverride.originalURI.spec,
-                          aOverride.originalURI.charset.get(),
-                          nullptr, io);
+                          nullptr, nullptr, io);
   if (NS_FAILED(rv))
     return;
 
   rv = NS_NewURI(getter_AddRefs(overrideURI), aOverride.overrideURI.spec,
-                 aOverride.overrideURI.charset.get(), nullptr, io);
+                 nullptr, nullptr, io);
   if (NS_FAILED(rv))
     return;
 
   mOverrideTable.Put(chromeURI, overrideURI);
 }
 
 nsIURI*
 nsChromeRegistryContent::GetBaseURIFromPackage(const nsCString& aPackage,
--- a/docshell/base/nsDefaultURIFixup.cpp
+++ b/docshell/base/nsDefaultURIFixup.cpp
@@ -82,24 +82,18 @@ nsDefaultURIFixup::CreateExposableURI(ns
     // Path is of the form "//123/http://foo/bar", with a variable number of
     // digits. To figure out where the "real" URL starts, search path for a '/',
     // starting at the third character.
     int32_t slashIndex = path.FindChar('/', 2);
     if (slashIndex == kNotFound) {
       return NS_ERROR_FAILURE;
     }
 
-    // Get the charset of the original URI so we can pass it to our fixed up
-    // URI.
-    nsAutoCString charset;
-    aURI->GetOriginCharset(charset);
-
     rv = NS_NewURI(getter_AddRefs(uri),
-                   Substring(path, slashIndex + 1, pathLength - slashIndex - 1),
-                   charset.get());
+                   Substring(path, slashIndex + 1, pathLength - slashIndex - 1));
     NS_ENSURE_SUCCESS(rv, rv);
   } else {
     // clone the URI so zapping user:pass doesn't change the original
     nsresult rv = aURI->Clone(getter_AddRefs(uri));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // hide user:pass unless overridden by pref
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -5282,23 +5282,20 @@ nsDocShell::DisplayLoadError(nsresult aE
       bool isFileURI = false;
       rv = aURI->SchemeIs("file", &isFileURI);
       if (NS_SUCCEEDED(rv) && isFileURI) {
         aURI->GetPathQueryRef(spec);
       } else {
         aURI->GetSpec(spec);
       }
 
-      nsAutoCString charset;
-      // unescape and convert from origin charset
-      aURI->GetOriginCharset(charset);
       nsCOMPtr<nsITextToSubURI> textToSubURI(
         do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv));
       if (NS_SUCCEEDED(rv)) {
-        rv = textToSubURI->UnEscapeURIForUI(charset, spec,
+        rv = textToSubURI->UnEscapeURIForUI(NS_LITERAL_CSTRING("UTF-8"), spec,
                                             formatStrs[formatStrCount]);
       }
     } else {
       spec.Assign('?');
     }
     if (NS_FAILED(rv)) {
       CopyUTF8toUTF16(spec, formatStrs[formatStrCount]);
     }
@@ -5382,40 +5379,36 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, 
   if (mLSHE) {
     // Abandon mLSHE's BFCache entry and create a new one.  This way, if
     // we go back or forward to another SHEntry with the same doc
     // identifier, the error page won't persist.
     mLSHE->AbandonBFCacheEntry();
   }
 
   nsAutoCString url;
-  nsAutoCString charset;
   if (aURI) {
     nsresult rv = aURI->GetSpec(url);
     NS_ENSURE_SUCCESS(rv, rv);
-    rv = aURI->GetOriginCharset(charset);
-    NS_ENSURE_SUCCESS(rv, rv);
   } else if (aURL) {
     CopyUTF16toUTF8(aURL, url);
   } else {
     return NS_ERROR_INVALID_POINTER;
   }
 
   // Create a URL to pass all the error information through to the page.
 
 #undef SAFE_ESCAPE
 #define SAFE_ESCAPE(output, input, params)                                     \
   if (NS_WARN_IF(!NS_Escape(input, output, params))) {                         \
     return NS_ERROR_OUT_OF_MEMORY;                                             \
   }
 
-  nsCString escapedUrl, escapedCharset, escapedError, escapedDescription,
+  nsCString escapedUrl, escapedError, escapedDescription,
     escapedCSSClass;
   SAFE_ESCAPE(escapedUrl, url, url_Path);
-  SAFE_ESCAPE(escapedCharset, charset, url_Path);
   SAFE_ESCAPE(escapedError, nsDependentCString(aErrorType), url_Path);
   SAFE_ESCAPE(escapedDescription,
               NS_ConvertUTF16toUTF8(aDescription), url_Path);
   if (aCSSClass) {
     nsCString cssClass(aCSSClass);
     SAFE_ESCAPE(escapedCSSClass, cssClass, url_Path);
   }
   nsCString errorPageUrl("about:");
@@ -5428,18 +5421,17 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, 
   if ((strcmp(aErrorPage, "blocked") == 0) &&
       Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE, true)) {
     errorPageUrl.AppendLiteral("&o=1");
   }
   if (!escapedCSSClass.IsEmpty()) {
     errorPageUrl.AppendLiteral("&s=");
     errorPageUrl.AppendASCII(escapedCSSClass.get());
   }
-  errorPageUrl.AppendLiteral("&c=");
-  errorPageUrl.AppendASCII(escapedCharset.get());
+  errorPageUrl.AppendLiteral("&c=UTF-8");
 
   nsAutoCString frameType(FrameTypeToString(mFrameType));
   errorPageUrl.AppendLiteral("&f=");
   errorPageUrl.AppendASCII(frameType.get());
 
   nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID);
   int32_t cpsState;
   if (cps && NS_SUCCEEDED(cps->GetState(&cpsState)) &&
@@ -12136,21 +12128,18 @@ nsDocShell::AddState(JS::Handle<JS::Valu
     nsIURI* docBaseURI = document->GetDocBaseURI();
     if (!docBaseURI) {
       return NS_ERROR_FAILURE;
     }
 
     nsAutoCString spec;
     docBaseURI->GetSpec(spec);
 
-    nsAutoCString charset;
-    rv = docBaseURI->GetOriginCharset(charset);
-    NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
-
-    rv = NS_NewURI(getter_AddRefs(newURI), aURL, charset.get(), docBaseURI);
+    rv = NS_NewURI(getter_AddRefs(newURI), aURL,
+                   document->GetDocumentCharacterSet(), docBaseURI);
 
     // 2b: If 2a fails, raise a SECURITY_ERR
     if (NS_FAILED(rv)) {
       return NS_ERROR_DOM_SECURITY_ERR;
     }
 
     // 2c: Same-origin check.
     if (!nsContentUtils::URIIsLocalFile(newURI)) {
--- a/dom/base/Link.cpp
+++ b/dom/base/Link.cpp
@@ -508,17 +508,18 @@ Link::SetSearch(const nsAString& aSearch
 {
   nsCOMPtr<nsIURI> uri(GetURIToMutate());
   nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
   if (!url) {
     // Ignore failures to be compatible with NS4.
     return;
   }
 
-  (void)url->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
+  auto encoding = mElement->OwnerDoc()->GetDocumentCharacterSet();
+  (void)url->SetQueryWithEncoding(NS_ConvertUTF16toUTF8(aSearch), encoding);
   SetHrefAttribute(uri);
 }
 
 void
 Link::SetPort(const nsAString &aPort)
 {
   nsCOMPtr<nsIURI> uri(GetURIToMutate());
   if (!uri) {
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -816,17 +816,22 @@ Location::SetSearch(const nsAString& aSe
 
   nsCOMPtr<nsIURI> uri;
   aRv = GetWritableURI(getter_AddRefs(uri));
   nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
   if (NS_WARN_IF(aRv.Failed()) || !url) {
     return;
   }
 
-  aRv = url->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
+  if (nsIDocument* doc = GetEntryDocument()) {
+    aRv = url->SetQueryWithEncoding(NS_ConvertUTF16toUTF8(aSearch),
+                                    doc->GetDocumentCharacterSet());
+  } else {
+    aRv = url->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
+  }
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   aRv = SetURI(uri);
 }
 
 nsresult
--- a/dom/base/nsReferencedElement.cpp
+++ b/dom/base/nsReferencedElement.cpp
@@ -23,37 +23,33 @@ nsReferencedElement::Reset(nsIContent* a
   Unlink();
 
   if (!aURI)
     return;
 
   nsAutoCString refPart;
   aURI->GetRef(refPart);
   // Unescape %-escapes in the reference. The result will be in the
-  // origin charset of the URL, hopefully...
+  // document charset, hopefully...
   NS_UnescapeURL(refPart);
 
-  nsAutoCString charset;
-  aURI->GetOriginCharset(charset);
-  auto encoding = Encoding::ForLabelNoReplacement(charset);
-  if (!encoding) {
-    encoding = UTF_8_ENCODING;
+  // Get the current document
+  nsIDocument *doc = aFromContent->OwnerDoc();
+  if (!doc) {
+    return;
   }
+
+  auto encoding = doc->GetDocumentCharacterSet();
   nsAutoString ref;
   nsresult rv = encoding->DecodeWithoutBOMHandling(refPart, ref);
   if (NS_FAILED(rv) || ref.IsEmpty()) {
     return;
   }
   rv = NS_OK;
 
-  // Get the current document
-  nsIDocument *doc = aFromContent->OwnerDoc();
-  if (!doc)
-    return;
-
   nsIContent* bindingParent = aFromContent->GetBindingParent();
   if (bindingParent) {
     nsXBLBinding* binding = bindingParent->GetXBLBinding();
     if (!binding) {
       // This happens, for example, if aFromContent is part of the content
       // inserted by a call to nsIDocument::InsertAnonymousContent, which we
       // also want to handle.  (It also happens for <use>'s anonymous
       // content etc.)
--- a/dom/html/MediaDocument.cpp
+++ b/dom/html/MediaDocument.cpp
@@ -290,27 +290,22 @@ MediaDocument::GetFileName(nsAString& aR
   if (fileName.IsEmpty())
     return;
 
   nsAutoCString docCharset;
   // Now that the charset is set in |StartDocumentLoad| to the charset of
   // the document viewer instead of a bogus value ("windows-1252" set in
   // |nsDocument|'s ctor), the priority is given to the current charset.
   // This is necessary to deal with a media document being opened in a new
-  // window or a new tab, in which case |originCharset| of |nsIURI| is not
-  // reliable.
+  // window or a new tab.
   if (mCharacterSetSource != kCharsetUninitialized) {
     mCharacterSet->Name(docCharset);
   } else {
-    // resort to |originCharset|
-    url->GetOriginCharset(docCharset);
-    auto encoding = Encoding::ForLabelNoReplacement(docCharset);
-    if (encoding) {
-      SetDocumentCharacterSet(WrapNotNull(encoding));
-    }
+    // resort to UTF-8
+    SetDocumentCharacterSet(UTF_8_ENCODING);
   }
 
   nsresult rv;
   nsCOMPtr<nsITextToSubURI> textToSubURI =
     do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
   if (NS_SUCCEEDED(rv)) {
     // UnEscapeURIForUI always succeeds
     textToSubURI->UnEscapeURIForUI(docCharset, fileName, aResult);
--- a/image/decoders/icon/nsIconURI.cpp
+++ b/image/decoders/icon/nsIconURI.cpp
@@ -411,16 +411,23 @@ nsMozIconURI::GetQuery(nsACString& aQuer
 
 NS_IMETHODIMP
 nsMozIconURI::SetQuery(const nsACString& aQuery)
 {
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
+nsMozIconURI::SetQueryWithEncoding(const nsACString& aQuery,
+                                   const Encoding* aEncoding)
+{
+  return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
 nsMozIconURI::GetRef(nsACString& aRef)
 {
   aRef.Truncate();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMozIconURI::SetRef(const nsACString& aRef)
@@ -536,23 +543,16 @@ nsMozIconURI::GetAsciiHostPort(nsACStrin
 }
 
 NS_IMETHODIMP
 nsMozIconURI::GetAsciiHost(nsACString& aHostA)
 {
   return GetHost(aHostA);
 }
 
-NS_IMETHODIMP
-nsMozIconURI::GetOriginCharset(nsACString& result)
-{
-  result.Truncate();
-  return NS_OK;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // nsIIconUri methods:
 
 NS_IMETHODIMP
 nsMozIconURI::GetIconURL(nsIURL** aFileUrl)
 {
   *aFileUrl = mIconURL;
   NS_IF_ADDREF(*aFileUrl);
--- a/ipc/glue/URIParams.ipdlh
+++ b/ipc/glue/URIParams.ipdlh
@@ -38,17 +38,16 @@ struct StandardURLParams
   StandardURLSegment host;
   StandardURLSegment path;
   StandardURLSegment filePath;
   StandardURLSegment directory;
   StandardURLSegment baseName;
   StandardURLSegment extension;
   StandardURLSegment query;
   StandardURLSegment ref;
-  nsCString originCharset;
   bool isMutable;
   bool supportsFileURL;
 };
 
 struct JARURIParams
 {
   URIParams jarFile;
   URIParams jarEntry;
--- a/modules/libjar/nsJARURI.cpp
+++ b/modules/libjar/nsJARURI.cpp
@@ -471,23 +471,16 @@ nsJARURI::GetAsciiHostPort(nsACString &a
 
 NS_IMETHODIMP
 nsJARURI::GetAsciiHost(nsACString &aHost)
 {
     return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-nsJARURI::GetOriginCharset(nsACString &aOriginCharset)
-{
-    aOriginCharset = mCharsetHint;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
 nsJARURI::Equals(nsIURI *other, bool *result)
 {
     return EqualsInternal(other, eHonorRef, result);
 }
 
 NS_IMETHODIMP
 nsJARURI::EqualsExceptRef(nsIURI *other, bool *result)
 {
@@ -621,16 +614,23 @@ nsJARURI::GetQuery(nsACString& query)
 
 NS_IMETHODIMP
 nsJARURI::SetQuery(const nsACString& query)
 {
     return mJAREntry->SetQuery(query);
 }
 
 NS_IMETHODIMP
+nsJARURI::SetQueryWithEncoding(const nsACString& query,
+                               const Encoding* encoding)
+{
+    return mJAREntry->SetQueryWithEncoding(query, encoding);
+}
+
+NS_IMETHODIMP
 nsJARURI::GetRef(nsACString& ref)
 {
     return mJAREntry->GetRef(ref);
 }
 
 NS_IMETHODIMP
 nsJARURI::SetRef(const nsACString& ref)
 {
@@ -723,22 +723,18 @@ nsJARURI::GetCommonBaseSpec(nsIURI* uriT
 
     }
 
     // At this point we have the same JAR file.  Compare the JAREntrys
     nsAutoCString otherEntry;
     rv = otherJARURI->GetJAREntry(otherEntry);
     if (NS_FAILED(rv)) return rv;
 
-    nsAutoCString otherCharset;
-    rv = uriToCompare->GetOriginCharset(otherCharset);
-    if (NS_FAILED(rv)) return rv;
-
     nsCOMPtr<nsIURL> url;
-    rv = CreateEntryURL(otherEntry, otherCharset.get(), getter_AddRefs(url));
+    rv = CreateEntryURL(otherEntry, nullptr, getter_AddRefs(url));
     if (NS_FAILED(rv)) return rv;
 
     nsAutoCString common;
     rv = mJAREntry->GetCommonBaseSpec(url, common);
     if (NS_FAILED(rv)) return rv;
 
     rv = FormatSpec(common, commonSpec);
     return rv;
@@ -770,22 +766,18 @@ nsJARURI::GetRelativeSpec(nsIURI* uriToC
         return rv;
     }
 
     // Same JAR file.  Compare the JAREntrys
     nsAutoCString otherEntry;
     rv = otherJARURI->GetJAREntry(otherEntry);
     if (NS_FAILED(rv)) return rv;
 
-    nsAutoCString otherCharset;
-    rv = uriToCompare->GetOriginCharset(otherCharset);
-    if (NS_FAILED(rv)) return rv;
-
     nsCOMPtr<nsIURL> url;
-    rv = CreateEntryURL(otherEntry, otherCharset.get(), getter_AddRefs(url));
+    rv = CreateEntryURL(otherEntry, nullptr, getter_AddRefs(url));
     if (NS_FAILED(rv)) return rv;
 
     nsAutoCString relativeEntrySpec;
     rv = mJAREntry->GetRelativeSpec(url, relativeEntrySpec);
     if (NS_FAILED(rv)) return rv;
 
     if (!StringBeginsWith(relativeEntrySpec, NS_BOGUS_ENTRY_SCHEME)) {
         // An actual relative spec!
--- a/netwerk/base/RustURL.cpp
+++ b/netwerk/base/RustURL.cpp
@@ -360,23 +360,16 @@ RustURL::GetAsciiHostPort(nsACString & a
 
 NS_IMETHODIMP
 RustURL::GetAsciiHost(nsACString & aAsciiHost)
 {
   return GetHost(aAsciiHost);
 }
 
 NS_IMETHODIMP
-RustURL::GetOriginCharset(nsACString & aOriginCharset)
-{
-  aOriginCharset.AssignLiteral("UTF-8");
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 RustURL::GetRef(nsACString & aRef)
 {
   return rusturl_get_fragment(mURL.get(), &aRef);
 }
 
 NS_IMETHODIMP
 RustURL::SetRef(const nsACString & aRef)
 {
@@ -491,16 +484,25 @@ RustURL::GetQuery(nsACString & aQuery)
 NS_IMETHODIMP
 RustURL::SetQuery(const nsACString & aQuery)
 {
   ENSURE_MUTABLE();
   return rusturl_set_query(mURL.get(), &aQuery);
 }
 
 NS_IMETHODIMP
+RustURL::SetQueryWithEncoding(const nsACString& aQuery,
+                              const Encoding* aEncoding)
+{
+  ENSURE_MUTABLE();
+  //XXX rust-url-capi should support the concept of "encoding override"
+  return rusturl_set_query(mURL.get(), &aQuery);
+}
+
+NS_IMETHODIMP
 RustURL::GetDirectory(nsACString & aDirectory)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 RustURL::SetDirectory(const nsACString & aDirectory)
 {
--- a/netwerk/base/RustURL.h
+++ b/netwerk/base/RustURL.h
@@ -15,17 +15,17 @@
 #include "nsISensitiveInfoHiddenURI.h"
 
 #include "rust-url-capi/src/rust-url-capi.h"
 #include "mozilla/UniquePtr.h"
 
 namespace mozilla {
 namespace net {
 
-class RustURL
+class RustURL final
   : public nsIFileURL
   , public nsIStandardURL
   , public nsISerializable
   , public nsIClassInfo
   , public nsISizeOf
   , public nsIIPCSerializableURI
   , public nsISensitiveInfoHiddenURI
 {
--- a/netwerk/base/nsIURI.idl
+++ b/netwerk/base/nsIURI.idl
@@ -35,18 +35,24 @@
  * [3] https://tools.ietf.org/html/rfc3987
  */
 
 %{C++
 #include "nsStringGlue.h"
 
 #undef GetPort  // XXX Windows!
 #undef SetPort  // XXX Windows!
+
+namespace mozilla {
+class Encoding;
+}
 %}
 
+[ptr] native Encoding(const mozilla::Encoding);
+
 /**
  * nsIURI - interface for an uniform resource identifier w/ i18n support.
  *
  * AUTF8String attributes may contain unescaped UTF-8 characters.
  * Consumers should be careful to escape the UTF-8 strings as necessary, but
  * should always try to "display" the UTF-8 version as provided by this
  * interface.
  *
@@ -225,27 +231,16 @@ interface nsIURI : nsISupports
 
     /**
      * The URI host with an ASCII compatible encoding.  Follows the IDNA
      * draft spec for converting internationalized domain names (UTF-8) to
      * ASCII for compatibility with existing internet infrasture.
      */
     readonly attribute ACString asciiHost;
 
-    /**
-     * The charset of the document from which this URI originated.  An empty
-     * value implies UTF-8.
-     *
-     * If this value is something other than UTF-8 then the URI components
-     * (e.g., spec, prePath, username, etc.) will all be fully URL-escaped.
-     * Otherwise, the URI components may contain unescaped multibyte UTF-8
-     * characters.
-     */
-    readonly attribute ACString originCharset;
-
     /************************************************************************
      * Additional attribute & methods added for .ref support:
      */
 
     /**
      * Returns the reference portion (the part after the "#") of the URI.
      * If there isn't one, an empty string is returned.
      *
@@ -298,16 +293,18 @@ interface nsIURI : nsISupports
 
     /**
      * Returns the query portion (the part after the "?") of the URL.
      * If there isn't one, an empty string is returned.
      *
      * Some characters may be escaped.
      */
     attribute AUTF8String query;
+    [noscript]
+    void setQueryWithEncoding(in AUTF8String query, in Encoding encoding);
 
     /**
      * If the URI has a punycode encoded hostname, this will hold the UTF8
      * representation of that hostname (if that representation doesn't contain
      * blacklisted characters, and the network.IDN_show_punycode pref is false)
      * Otherwise, if the hostname is ASCII, it will return the same as .asciiHost
      */
     readonly attribute AUTF8String displayHost;
--- a/netwerk/base/nsNetUtil.cpp
+++ b/netwerk/base/nsNetUtil.cpp
@@ -2391,26 +2391,18 @@ uint32_t
 NS_GetContentDispositionFromHeader(const nsACString &aHeader,
                                    nsIChannel *aChan /* = nullptr */)
 {
   nsresult rv;
   nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar = do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv);
   if (NS_FAILED(rv))
     return nsIChannel::DISPOSITION_ATTACHMENT;
 
-  nsAutoCString fallbackCharset;
-  if (aChan) {
-    nsCOMPtr<nsIURI> uri;
-    aChan->GetURI(getter_AddRefs(uri));
-    if (uri)
-      uri->GetOriginCharset(fallbackCharset);
-  }
-
   nsAutoString dispToken;
-  rv = mimehdrpar->GetParameterHTTP(aHeader, "", fallbackCharset, true, nullptr,
+  rv = mimehdrpar->GetParameterHTTP(aHeader, "", EmptyCString(), true, nullptr,
                                     dispToken);
 
   if (NS_FAILED(rv)) {
     // special case (see bug 272541): empty disposition type handled as "inline"
     if (rv == NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY)
         return nsIChannel::DISPOSITION_INLINE;
     return nsIChannel::DISPOSITION_ATTACHMENT;
   }
@@ -2426,24 +2418,19 @@ NS_GetFilenameFromDisposition(nsAString 
   aFilename.Truncate();
 
   nsresult rv;
   nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar =
       do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv);
   if (NS_FAILED(rv))
     return rv;
 
-  nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
-
-  nsAutoCString fallbackCharset;
-  if (url)
-    url->GetOriginCharset(fallbackCharset);
   // Get the value of 'filename' parameter
   rv = mimehdrpar->GetParameterHTTP(aDisposition, "filename",
-                                    fallbackCharset, true, nullptr,
+                                    EmptyCString(), true, nullptr,
                                     aFilename);
 
   if (NS_FAILED(rv)) {
     aFilename.Truncate();
     return rv;
   }
 
   if (aFilename.IsEmpty())
--- a/netwerk/base/nsSimpleURI.cpp
+++ b/netwerk/base/nsSimpleURI.cpp
@@ -706,23 +706,16 @@ nsSimpleURI::GetAsciiHostPort(nsACString
 
 NS_IMETHODIMP
 nsSimpleURI::GetAsciiHost(nsACString &result)
 {
     result.Truncate();
     return NS_OK;
 }
 
-NS_IMETHODIMP
-nsSimpleURI::GetOriginCharset(nsACString &result)
-{
-    result.Truncate();
-    return NS_OK;
-}
-
 //----------------------------------------------------------------------------
 // nsSimpleURI::nsIClassInfo
 //----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsSimpleURI::GetInterfaces(uint32_t *count, nsIID * **array)
 {
     *count = 0;
@@ -865,10 +858,17 @@ nsSimpleURI::SetQuery(const nsACString& 
         mQuery = Substring(query, 1);
     } else {
         mQuery = query;
     }
 
     return NS_OK;
 }
 
+NS_IMETHODIMP
+nsSimpleURI::SetQueryWithEncoding(const nsACString& aQuery,
+                                  const Encoding* aEncoding)
+{
+    return SetQuery(aQuery);
+}
+
 } // namespace net
 } // namespace mozilla
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -204,19 +204,18 @@ nsPrefObserver::Observe(nsISupports *sub
     }
     return NS_OK;
 }
 
 //----------------------------------------------------------------------------
 // nsStandardURL::nsSegmentEncoder
 //----------------------------------------------------------------------------
 
-nsStandardURL::nsSegmentEncoder::nsSegmentEncoder(const char* charset)
-  : mEncoding(charset ? Encoding::ForLabelNoReplacement(MakeStringSpan(charset))
-                      : nullptr)
+nsStandardURL::nsSegmentEncoder::nsSegmentEncoder(const Encoding* encoding)
+  : mEncoding(encoding)
 {
   if (mEncoding == UTF_8_ENCODING) {
     mEncoding = nullptr;
   }
 }
 
 int32_t nsStandardURL::
 nsSegmentEncoder::EncodeSegmentCount(const char *str,
@@ -280,25 +279,16 @@ nsSegmentEncoder::EncodeSegment(const ns
     const char *text;
     bool encoded;
     EncodeSegmentCount(str.BeginReading(text), URLSegment(0, str.Length()), mask, result, encoded);
     if (encoded)
         return result;
     return str;
 }
 
-#define GET_SEGMENT_ENCODER_INTERNAL(name, useUTF8) \
-    nsSegmentEncoder name(useUTF8 ? nullptr : mOriginCharset.get())
-
-#define GET_SEGMENT_ENCODER(name) \
-    GET_SEGMENT_ENCODER_INTERNAL(name, true)
-
-#define GET_QUERY_ENCODER(name) \
-    GET_SEGMENT_ENCODER_INTERNAL(name, false)
-
 //----------------------------------------------------------------------------
 // nsStandardURL <public>
 //----------------------------------------------------------------------------
 
 #ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
 static LinkedList<nsStandardURL> gAllURLs;
 #endif
 
@@ -789,17 +779,18 @@ nsStandardURL::AppendToBuf(char *buf, ui
 }
 
 // basic algorithm:
 //  1- escape url segments (for improved GetSpec efficiency)
 //  2- allocate spec buffer
 //  3- write url segments
 //  4- update url segment positions and lengths
 nsresult
-nsStandardURL::BuildNormalizedSpec(const char *spec)
+nsStandardURL::BuildNormalizedSpec(const char *spec,
+                                   const Encoding* encoding)
 {
     // Assumptions: all member URLSegments must be relative the |spec| argument
     // passed to this function.
 
     // buffers for holding escaped url segments (these will remain empty unless
     // escaping is required).
     nsAutoCString encUsername, encPassword, encHost, encDirectory,
       encBasename, encExtension, encQuery, encRef;
@@ -818,18 +809,18 @@ nsStandardURL::BuildNormalizedSpec(const
     // the scheme is already ASCII
     if (mScheme.mLen > 0)
         approxLen += mScheme.mLen + 3; // includes room for "://", which we insert always
 
     // encode URL segments; convert UTF-8 to origin charset and possibly escape.
     // results written to encXXX variables only if |spec| is not already in the
     // appropriate encoding.
     {
-        GET_SEGMENT_ENCODER(encoder);
-        GET_QUERY_ENCODER(queryEncoder);
+        nsSegmentEncoder encoder;
+        nsSegmentEncoder queryEncoder(encoding);
         // Items using an extraLen of 1 don't add anything unless mLen > 0
         // Username@
         approxLen += encoder.EncodeSegmentCount(spec, mUsername,  esc_Username,      encUsername,  useEncUsername, 1);
         // :password - we insert the ':' even if there's no actual password if "user:@" was in the spec
         if (mPassword.mLen >= 0)
             approxLen += 1 + encoder.EncodeSegmentCount(spec, mPassword,  esc_Password,      encPassword,  useEncPassword);
         // mHost is handled differently below due to encoding differences
         MOZ_ASSERT(mPort >= -1, "Invalid negative mPort");
@@ -1649,27 +1640,16 @@ nsStandardURL::GetAsciiHostPort(nsACStri
 NS_IMETHODIMP
 nsStandardURL::GetAsciiHost(nsACString &result)
 {
     result = Host();
     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);
     nsACString::const_iterator iterator(start);
     input.EndReading(end);
 
@@ -1686,16 +1666,23 @@ IsSpecialProtocol(const nsACString &inpu
            protocol.LowerCaseEqualsLiteral("wss") ||
            protocol.LowerCaseEqualsLiteral("file") ||
            protocol.LowerCaseEqualsLiteral("gopher");
 }
 
 NS_IMETHODIMP
 nsStandardURL::SetSpec(const nsACString &input)
 {
+    return SetSpecWithEncoding(input, nullptr);
+}
+
+nsresult
+nsStandardURL::SetSpecWithEncoding(const nsACString &input,
+                                   const Encoding* encoding)
+{
     ENSURE_MUTABLE();
 
     const nsPromiseFlatCString &flat = PromiseFlatCString(input);
     LOG(("nsStandardURL::SetSpec [spec=%s]\n", flat.get()));
 
     if (input.Length() > (uint32_t) net_GetURLMaxLength()) {
         return NS_ERROR_MALFORMED_URI;
     }
@@ -1734,17 +1721,17 @@ nsStandardURL::SetSpec(const nsACString 
     const char *spec = filteredURI.get();
     int32_t specLength = filteredURI.Length();
 
     // parse the given URL...
     nsresult rv = ParseURL(spec, specLength);
     if (NS_SUCCEEDED(rv)) {
         // finally, use the URLSegment member variables to build a normalized
         // copy of |spec|
-        rv = BuildNormalizedSpec(spec);
+        rv = BuildNormalizedSpec(spec, encoding);
     }
 
     // Make sure that a URLTYPE_AUTHORITY has a non-empty hostname.
     if (mURLType == URLTYPE_AUTHORITY && mHost.mLen == -1) {
         rv = NS_ERROR_MALFORMED_URI;
     }
 
     if (NS_FAILED(rv)) {
@@ -1873,17 +1860,17 @@ nsStandardURL::SetUserPass(const nsACStr
     rv = mParser->ParseUserInfo(userpass.get(), userpass.Length(),
                                 &usernamePos, &usernameLen,
                                 &passwordPos, &passwordLen);
     if (NS_FAILED(rv)) return rv;
 
     // build new user:pass in |buf|
     nsAutoCString buf;
     if (usernameLen > 0) {
-        GET_SEGMENT_ENCODER(encoder);
+        nsSegmentEncoder encoder;
         bool ignoredOut;
         usernameLen = encoder.EncodeSegmentCount(userpass.get(),
                                                  URLSegment(usernamePos,
                                                             usernameLen),
                                                  esc_Username | esc_AlwaysCopy,
                                                  buf, ignoredOut);
         if (passwordLen > 0) {
             buf.Append(':');
@@ -1955,17 +1942,17 @@ nsStandardURL::SetUsername(const nsACStr
     if (mSpec.Length() + input.Length() - Username().Length() > (uint32_t) net_GetURLMaxLength()) {
         return NS_ERROR_MALFORMED_URI;
     }
 
     InvalidateCache();
 
     // escape username if necessary
     nsAutoCString buf;
-    GET_SEGMENT_ENCODER(encoder);
+    nsSegmentEncoder encoder;
     const nsACString &escUsername =
         encoder.EncodeSegment(username, esc_Username, buf);
 
     int32_t shift;
 
     if (mUsername.mLen < 0) {
         mUsername.mPos = mAuthority.mPos;
         mSpec.Insert(escUsername + NS_LITERAL_CSTRING("@"), mUsername.mPos);
@@ -2019,17 +2006,17 @@ nsStandardURL::SetPassword(const nsACStr
             mPassword.mLen = -1;
         }
         CALL_RUST_SETTER(SetPassword, input);
         return NS_OK;
     }
 
     // escape password if necessary
     nsAutoCString buf;
-    GET_SEGMENT_ENCODER(encoder);
+    nsSegmentEncoder encoder;
     const nsACString &escPassword =
         encoder.EncodeSegment(password, esc_Password, buf);
 
     int32_t shift;
 
     if (mPassword.mLen < 0) {
         mPassword.mPos = mUsername.mPos + mUsername.mLen + 1;
         mSpec.Insert(NS_LITERAL_CSTRING(":") + escPassword, mPassword.mPos - 1);
@@ -2535,17 +2522,16 @@ nsresult nsStandardURL::CopyMembers(nsSt
     mHost = source->mHost;
     mPath = source->mPath;
     mFilepath = source->mFilepath;
     mDirectory = source->mDirectory;
     mBasename = source->mBasename;
     mExtension = source->mExtension;
     mQuery = source->mQuery;
     mRef = source->mRef;
-    mOriginCharset = source->mOriginCharset;
     mURLType = source->mURLType;
     mParser = source->mParser;
     mMutable = true;
     mSupportsFileURL = source->mSupportsFileURL;
 
     COPY_RUST_MEMBER;
     if (copyCached) {
         mFile = source->mFile;
@@ -2989,17 +2975,17 @@ nsStandardURL::SetFilePath(const nsACStr
 
         // build up new candidate spec
         spec.Assign(mSpec.get(), mPath.mPos);
 
         // ensure leading '/'
         if (filepath[dirPos] != '/')
             spec.Append('/');
 
-        GET_SEGMENT_ENCODER(encoder);
+        nsSegmentEncoder encoder;
 
         // append encoded filepath components
         if (dirLen > 0)
             encoder.EncodeSegment(Substring(filepath + dirPos,
                                             filepath + dirPos + dirLen),
                                   esc_Directory | esc_AlwaysCopy, spec);
         if (baseLen > 0)
             encoder.EncodeSegment(Substring(filepath + basePos,
@@ -3033,26 +3019,45 @@ nsStandardURL::SetFilePath(const nsACStr
         mFilepath.mLen = 1;
         // these are no longer defined
         mBasename.mLen = -1;
         mExtension.mLen = -1;
     }
     return NS_OK;
 }
 
+inline bool
+IsUTFEncoding(const Encoding* aEncoding)
+{
+    return aEncoding == UTF_8_ENCODING ||
+           aEncoding == UTF_16BE_ENCODING ||
+           aEncoding == UTF_16LE_ENCODING;
+}
+
 NS_IMETHODIMP
 nsStandardURL::SetQuery(const nsACString &input)
 {
+    return SetQueryWithEncoding(input, nullptr);
+}
+
+NS_IMETHODIMP
+nsStandardURL::SetQueryWithEncoding(const nsACString &input,
+                                    const Encoding* encoding)
+{
     ENSURE_MUTABLE();
 
     const nsPromiseFlatCString &flat = PromiseFlatCString(input);
     const char *query = flat.get();
 
     LOG(("nsStandardURL::SetQuery [query=%s]\n", query));
 
+    if (IsUTFEncoding(encoding)) {
+        encoding = nullptr;
+    }
+
     if (mPath.mLen < 0)
         return SetPathQueryRef(flat);
 
     if (mSpec.Length() + input.Length() - Query().Length() > (uint32_t) net_GetURLMaxLength()) {
         return NS_ERROR_MALFORMED_URI;
     }
 
     InvalidateCache();
@@ -3088,17 +3093,17 @@ nsStandardURL::SetQuery(const nsACString
         // the insertion pushes these out by 1
         mPath.mLen++;
         mRef.mPos++;
     }
 
     // encode query if necessary
     nsAutoCString buf;
     bool encoded;
-    GET_QUERY_ENCODER(encoder);
+    nsSegmentEncoder encoder(encoding);
     encoder.EncodeSegmentCount(query, URLSegment(0, queryLen), esc_Query,
                                buf, encoded);
     if (encoded) {
         query = buf.get();
         queryLen = buf.Length();
     }
 
     int32_t shift = ReplaceSegment(mQuery.mPos, mQuery.mLen, query, queryLen);
@@ -3157,17 +3162,17 @@ nsStandardURL::SetRef(const nsACString &
         mRef.mLen = 0;
     }
 
     // If precent encoding is necessary, `ref` will point to `buf`'s content.
     // `buf` needs to outlive any use of the `ref` pointer.
     nsAutoCString buf;
     // encode ref if necessary
     bool encoded;
-    GET_SEGMENT_ENCODER(encoder);
+    nsSegmentEncoder encoder;
     encoder.EncodeSegmentCount(ref, URLSegment(0, refLen), esc_Ref,
                                buf, encoded);
     if (encoded) {
         ref = buf.get();
         refLen = buf.Length();
     }
 
     int32_t shift = ReplaceSegment(mRef.mPos, mRef.mLen, ref, refLen);
@@ -3234,17 +3239,17 @@ nsStandardURL::SetFileName(const nsACStr
                 shift = -int32_t(len);
                 mBasename.mLen = 0;
                 mExtension.mLen = -1;
             }
         }
         else {
             nsAutoCString newFilename;
             bool ignoredOut;
-            GET_SEGMENT_ENCODER(encoder);
+            nsSegmentEncoder encoder;
             basename.mLen = encoder.EncodeSegmentCount(filename, basename,
                                                        esc_FileBaseName |
                                                        esc_AlwaysCopy,
                                                        newFilename,
                                                        ignoredOut);
             if (extension.mLen >= 0) {
                 newFilename.Append('.');
                 extension.mLen = encoder.EncodeSegmentCount(filename, extension,
@@ -3402,24 +3407,16 @@ nsStandardURL::SetFile(nsIFile *file)
 
     return NS_OK;
 }
 
 //----------------------------------------------------------------------------
 // nsStandardURL::nsIStandardURL
 //----------------------------------------------------------------------------
 
-inline bool
-IsUTFCharset(const char *aCharset)
-{
-    return ((aCharset[0] == 'U' || aCharset[0] == 'u') &&
-            (aCharset[1] == 'T' || aCharset[1] == 't') &&
-            (aCharset[2] == 'F' || aCharset[2] == 'f'));
-}
-
 NS_IMETHODIMP
 nsStandardURL::Init(uint32_t urlType,
                     int32_t defaultPort,
                     const nsACString &spec,
                     const char *charset,
                     nsIURI *baseURI)
 {
     ENSURE_MUTABLE();
@@ -3443,51 +3440,40 @@ nsStandardURL::Init(uint32_t urlType,
         break;
     default:
         NS_NOTREACHED("bad urlType");
         return NS_ERROR_INVALID_ARG;
     }
     mDefaultPort = defaultPort;
     mURLType = urlType;
 
-    mOriginCharset.Truncate();
-
-    if (charset == nullptr || *charset == '\0') {
-        // check if baseURI provides an origin charset and use that.
-        if (baseURI)
-            baseURI->GetOriginCharset(mOriginCharset);
-
-        // URI can't be encoded in UTF-16, UTF-16BE, UTF-16LE, UTF-32,
-        // UTF-32-LE, UTF-32LE, UTF-32BE (yet?). Truncate mOriginCharset if
-        // it starts with "utf" (since an empty mOriginCharset implies
-        // UTF-8, this is safe even if mOriginCharset is UTF-8).
-
-        if (mOriginCharset.Length() > 3 &&
-            IsUTFCharset(mOriginCharset.get())) {
-            mOriginCharset.Truncate();
-        }
-    }
-    else if (!IsUTFCharset(charset)) {
-        mOriginCharset = charset;
+    auto encoding =
+        charset ? Encoding::ForLabelNoReplacement(MakeStringSpan(charset))
+                : nullptr;
+    // URI can't be encoded in UTF-16BE or UTF-16LE. Truncate encoding
+    // if it is one of utf encodings (since a null encoding implies
+    // UTF-8, this is safe even if encoding is UTF-8).
+    if (IsUTFEncoding(encoding)) {
+        encoding = nullptr;
     }
 
     if (baseURI && net_IsAbsoluteURL(spec)) {
         baseURI = nullptr;
     }
 
     CALL_RUST_INIT;
 
     if (!baseURI)
-        return SetSpec(spec);
+        return SetSpecWithEncoding(spec, encoding);
 
     nsAutoCString buf;
     nsresult rv = baseURI->Resolve(spec, buf);
     if (NS_FAILED(rv)) return rv;
 
-    return SetSpec(buf);
+    return SetSpecWithEncoding(buf, encoding);
 }
 
 NS_IMETHODIMP
 nsStandardURL::SetDefaultPort(int32_t aNewDefaultPort)
 {
     ENSURE_MUTABLE();
 
     InvalidateCache();
@@ -3603,17 +3589,18 @@ nsStandardURL::Read(nsIObjectInputStream
     if (NS_FAILED(rv)) return rv;
 
     rv = ReadSegment(stream, mQuery);
     if (NS_FAILED(rv)) return rv;
 
     rv = ReadSegment(stream, mRef);
     if (NS_FAILED(rv)) return rv;
 
-    rv = NS_ReadOptionalCString(stream, mOriginCharset);
+    nsAutoCString oldOriginCharset;
+    rv = NS_ReadOptionalCString(stream, oldOriginCharset);
     if (NS_FAILED(rv)) return rv;
 
     bool isMutable;
     rv = stream->ReadBoolean(&isMutable);
     if (NS_FAILED(rv)) return rv;
     mMutable = isMutable;
 
     bool supportsFileURL;
@@ -3695,17 +3682,18 @@ nsStandardURL::Write(nsIObjectOutputStre
     if (NS_FAILED(rv)) return rv;
 
     rv = WriteSegment(stream, mQuery);
     if (NS_FAILED(rv)) return rv;
 
     rv = WriteSegment(stream, mRef);
     if (NS_FAILED(rv)) return rv;
 
-    rv = NS_WriteOptionalStringZ(stream, mOriginCharset.get());
+    // former origin charset
+    rv = NS_WriteOptionalStringZ(stream, EmptyCString().get());
     if (NS_FAILED(rv)) return rv;
 
     rv = stream->WriteBoolean(mMutable);
     if (NS_FAILED(rv)) return rv;
 
     rv = stream->WriteBoolean(mSupportsFileURL);
     if (NS_FAILED(rv)) return rv;
 
@@ -3750,17 +3738,16 @@ nsStandardURL::Serialize(URIParams& aPar
     params.host() = ToIPCSegment(mHost);
     params.path() = ToIPCSegment(mPath);
     params.filePath() = ToIPCSegment(mFilepath);
     params.directory() = ToIPCSegment(mDirectory);
     params.baseName() = ToIPCSegment(mBasename);
     params.extension() = ToIPCSegment(mExtension);
     params.query() = ToIPCSegment(mQuery);
     params.ref() = ToIPCSegment(mRef);
-    params.originCharset() = mOriginCharset;
     params.isMutable() = !!mMutable;
     params.supportsFileURL() = !!mSupportsFileURL;
     // mSpecEncoding and mDisplayHost are just caches that can be recovered as needed.
 
     aParams = params;
 }
 
 bool
@@ -3804,17 +3791,16 @@ nsStandardURL::Deserialize(const URIPara
     mHost = FromIPCSegment(params.host());
     mPath = FromIPCSegment(params.path());
     mFilepath = FromIPCSegment(params.filePath());
     mDirectory = FromIPCSegment(params.directory());
     mBasename = FromIPCSegment(params.baseName());
     mExtension = FromIPCSegment(params.extension());
     mQuery = FromIPCSegment(params.query());
     mRef = FromIPCSegment(params.ref());
-    mOriginCharset = params.originCharset();
     mMutable = params.isMutable();
     mSupportsFileURL = params.supportsFileURL();
 
     CALL_RUST_SYNC;
 
     // mSpecEncoding and mDisplayHost are just caches that can be recovered as needed.
     return true;
 }
@@ -3878,17 +3864,16 @@ nsStandardURL::GetClassIDNoAlloc(nsCID *
 //----------------------------------------------------------------------------
 // nsStandardURL::nsISizeOf
 //----------------------------------------------------------------------------
 
 size_t
 nsStandardURL::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
 {
   return mSpec.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
-         mOriginCharset.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
          mDisplayHost.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - mParser
   // - mFile
 }
 
--- a/netwerk/base/nsStandardURL.h
+++ b/netwerk/base/nsStandardURL.h
@@ -30,16 +30,17 @@
 class nsIBinaryInputStream;
 class nsIBinaryOutputStream;
 class nsIIDNService;
 class nsIPrefBranch;
 class nsIFile;
 class nsIURLParser;
 
 namespace mozilla {
+class Encoding;
 namespace net {
 
 //-----------------------------------------------------------------------------
 // standard URL implementation
 //-----------------------------------------------------------------------------
 
 class nsStandardURL : public nsIFileURL
                     , public nsIStandardURL
@@ -117,17 +118,17 @@ public: /* internal -- HPUX compiler can
     friend class nsPrefObserver;
 
     //
     // URL segment encoder : performs charset conversion and URL escaping.
     //
     class nsSegmentEncoder
     {
     public:
-        explicit nsSegmentEncoder(const char *charset);
+        explicit nsSegmentEncoder(const Encoding* encoding = nullptr);
 
         // Encode the given segment if necessary, and return the length of
         // the encoded segment.  The encoded segment is appended to |buf|
         // if and only if encoding is required.
         int32_t EncodeSegmentCount(const char *str,
                                    const URLSegment &segment,
                                    int16_t mask,
                                    nsCString& buf,
@@ -193,17 +194,18 @@ private:
     void     CoalescePath(netCoalesceFlags coalesceFlag, char *path);
 
     uint32_t AppendSegmentToBuf(char *, uint32_t, const char *,
                                 const URLSegment &input, URLSegment &output,
                                 const nsCString *esc=nullptr,
                                 bool useEsc = false, int32_t* diff = nullptr);
     uint32_t AppendToBuf(char *, uint32_t, const char *, uint32_t);
 
-    nsresult BuildNormalizedSpec(const char *spec);
+    nsresult BuildNormalizedSpec(const char* spec, const Encoding* encoding);
+    nsresult SetSpecWithEncoding(const nsACString &input, const Encoding* encoding);
 
     bool     SegmentIs(const URLSegment &s1, const char *val, bool ignoreCase = false);
     bool     SegmentIs(const char* spec, const URLSegment &s1, const char *val, bool ignoreCase = false);
     bool     SegmentIs(const URLSegment &s1, const char *val, const URLSegment &s2, bool ignoreCase = false);
 
     int32_t  ReplaceSegment(uint32_t pos, uint32_t len, const char *val, uint32_t valLen);
     int32_t  ReplaceSegment(uint32_t pos, uint32_t len, const nsACString &val);
 
@@ -269,17 +271,16 @@ private:
     URLSegment mPath;
     URLSegment mFilepath;
     URLSegment mDirectory;
     URLSegment mBasename;
     URLSegment mExtension;
     URLSegment mQuery;
     URLSegment mRef;
 
-    nsCString              mOriginCharset;
     nsCOMPtr<nsIURLParser> mParser;
 
     // mFile is protected so subclasses can access it directly
 protected:
     nsCOMPtr<nsIFile>      mFile;  // cached result for nsIFileURL::GetFile
 
 private:
     // cached result for nsIURI::GetDisplayHost
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -1589,24 +1589,19 @@ HttpBaseChannel::SetReferrerWithPolicy(n
     if (pathLength <= 2) return NS_ERROR_FAILURE;
 
     // Path is of the form "//123/http://foo/bar", with a variable number of
     // digits. To figure out where the "real" URL starts, search path for a
     // '/', starting at the third character.
     int32_t slashIndex = path.FindChar('/', 2);
     if (slashIndex == kNotFound) return NS_ERROR_FAILURE;
 
-    // Get charset of the original URI so we can pass it to our fixed up URI.
-    nsAutoCString charset;
-    referrer->GetOriginCharset(charset);
-
     // Replace |referrer| with a URI without wyciwyg://123/.
     rv = NS_NewURI(getter_AddRefs(referrerGrip),
-                   Substring(path, slashIndex + 1, pathLength - slashIndex - 1),
-                   charset.get());
+                   Substring(path, slashIndex + 1, pathLength - slashIndex - 1));
     if (NS_FAILED(rv)) return rv;
 
     referrer = referrerGrip.get();
   }
 
   //
   // block referrer if not on our white list...
   //
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -8380,24 +8380,18 @@ nsHttpChannel::OnLookupComplete(nsICance
 // Creates an URI to the given location using current URI for base and charset
 nsresult
 nsHttpChannel::CreateNewURI(const char *loc, nsIURI **newURI)
 {
     nsCOMPtr<nsIIOService> ioService;
     nsresult rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
     if (NS_FAILED(rv)) return rv;
 
-    // the new uri should inherit the origin charset of the current uri
-    nsAutoCString originCharset;
-    rv = mURI->GetOriginCharset(originCharset);
-    if (NS_FAILED(rv))
-        originCharset.Truncate();
-
     return ioService->NewURI(nsDependentCString(loc),
-                             originCharset.get(),
+                             nullptr,
                              mURI,
                              newURI);
 }
 
 void
 nsHttpChannel::MaybeInvalidateCacheEntryForSubsequentGet()
 {
     // See RFC 2616 section 5.1.1. These are considered valid
--- a/netwerk/protocol/res/SubstitutingProtocolHandler.cpp
+++ b/netwerk/protocol/res/SubstitutingProtocolHandler.cpp
@@ -117,17 +117,16 @@ nsresult
 SubstitutingProtocolHandler::CollectSubstitutions(InfallibleTArray<SubstitutionMapping>& aMappings)
 {
   for (auto iter = mSubstitutions.ConstIter(); !iter.Done(); iter.Next()) {
     nsCOMPtr<nsIURI> uri = iter.Data();
     SerializedURI serialized;
     if (uri) {
       nsresult rv = uri->GetSpec(serialized.spec);
       NS_ENSURE_SUCCESS(rv, rv);
-      uri->GetOriginCharset(serialized.charset);
     }
     SubstitutionMapping substitution = { mScheme, nsCString(iter.Key()), serialized };
     aMappings.AppendElement(substitution);
   }
 
   return NS_OK;
 }
 
@@ -145,17 +144,16 @@ SubstitutingProtocolHandler::SendSubstit
   }
 
   SubstitutionMapping mapping;
   mapping.scheme = mScheme;
   mapping.path = aRoot;
   if (aBaseURI) {
     nsresult rv = aBaseURI->GetSpec(mapping.resolvedURI.spec);
     NS_ENSURE_SUCCESS(rv, rv);
-    aBaseURI->GetOriginCharset(mapping.resolvedURI.charset);
   }
 
   for (uint32_t i = 0; i < parents.Length(); i++) {
     Unused << parents[i]->SendRegisterChromeItem(mapping);
   }
 
   return NS_OK;
 }
--- a/netwerk/streamconv/converters/nsIndexedToHTML.cpp
+++ b/netwerk/streamconv/converters/nsIndexedToHTML.cpp
@@ -489,25 +489,18 @@ nsIndexedToHTML::DoOnStartRequest(nsIReq
     // Everything needs to end in a /,
     // otherwise we end up linking to file:///foo/dirfile
 
     if (!mTextToSubURI) {
         mTextToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
         if (NS_FAILED(rv)) return rv;
     }
 
-    nsXPIDLCString encoding;
-    rv = uri->GetOriginCharset(encoding);
-    if (NS_FAILED(rv)) return rv;
-    if (encoding.IsEmpty()) {
-      encoding.AssignLiteral("UTF-8");
-    }
-
     nsAutoString unEscapeSpec;
-    rv = mTextToSubURI->UnEscapeAndConvert(encoding, titleUri, unEscapeSpec);
+    rv = mTextToSubURI->UnEscapeAndConvert(NS_LITERAL_CSTRING("UTF-8"), titleUri, unEscapeSpec);
     // unescape may fail because
     // 1. file URL may be encoded in platform charset for backward compatibility
     // 2. query part may not be encoded in UTF-8 (see bug 261929)
     // so try the platform's default if this is file url
     if (NS_FAILED(rv) && isSchemeFile) {
         nsCOMPtr<nsIPlatformCharset> platformCharset(do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv));
         NS_ENSURE_SUCCESS(rv, rv);
         nsAutoCString charset;
--- a/toolkit/content/contentAreaUtils.js
+++ b/toolkit/content/contentAreaUtils.js
@@ -398,18 +398,16 @@ function internalSave(aURL, aDocument, a
     sourceURI = aChosenData.uri;
     saveAsType = kSaveAsType_Complete;
 
     continueSave();
   } else {
     var charset = null;
     if (aDocument)
       charset = aDocument.characterSet;
-    else if (aReferrer)
-      charset = aReferrer.originCharset;
     var fileInfo = new FileInfo(aDefaultFileName);
     initFileInfo(fileInfo, aURL, charset, aDocument,
                  aContentType, aContentDisposition);
     sourceURI = fileInfo.uri;
 
     var fpParams = {
       fpTitleKey: aFilePickerTitleKey,
       fileInfo,
@@ -1029,17 +1027,17 @@ function getDefaultFileName(aDefaultFile
   }
 
   try {
     var url = aURI.QueryInterface(Components.interfaces.nsIURL);
     if (url.fileName != "") {
       // 3) Use the actual file name, if present
       var textToSubURI = Components.classes["@mozilla.org/intl/texttosuburi;1"]
                                    .getService(Components.interfaces.nsITextToSubURI);
-      return validateFileName(textToSubURI.unEscapeURIForUI(url.originCharset || "UTF-8", url.fileName));
+      return validateFileName(textToSubURI.unEscapeURIForUI("UTF-8", url.fileName));
     }
   } catch (e) {
     // This is something like a data: and so forth URI... no filename here.
   }
 
   if (docTitle)
     // 4) Use the document title
     return docTitle;
--- a/toolkit/modules/BrowserUtils.jsm
+++ b/toolkit/modules/BrowserUtils.jsm
@@ -179,17 +179,17 @@ this.BrowserUtils = {
   /**
    * @deprecated Use Services.io.newFileURI directly instead.
    */
   makeFileURI(aFile) {
     return Services.io.newFileURI(aFile);
   },
 
   makeURIFromCPOW(aCPOWURI) {
-    return Services.io.newURI(aCPOWURI.spec, aCPOWURI.originCharset);
+    return Services.io.newURI(aCPOWURI.spec);
   },
 
   /**
    * For a given DOM element, returns its position in "screen"
    * coordinates. In a content process, the coordinates returned will
    * be relative to the left/top of the tab. In the chrome process,
    * the coordinates are relative to the user's screen.
    */
--- a/toolkit/modules/sessionstore/SessionHistory.jsm
+++ b/toolkit/modules/sessionstore/SessionHistory.jsm
@@ -147,18 +147,16 @@ var SessionHistoryInternal = {
    */
   serializeEntry(shEntry) {
     let entry = { url: shEntry.URI.spec, title: shEntry.title };
 
     if (shEntry.isSubFrame) {
       entry.subframe = true;
     }
 
-    entry.charset = shEntry.URI.originCharset;
-
     let cacheKey = shEntry.cacheKey;
     if (cacheKey && cacheKey instanceof Ci.nsISupportsPRUint32 &&
         cacheKey.data != 0) {
       // XXXbz would be better to have cache keys implement
       // nsISerializable or something.
       entry.cacheKey = cacheKey.data;
     }
     entry.ID = shEntry.ID;
@@ -370,17 +368,17 @@ var SessionHistoryInternal = {
    *        Hash to ensure reuse of BFCache entries
    * @returns nsISHEntry
    */
   deserializeEntry(entry, idMap, docIdentMap) {
 
     var shEntry = Cc["@mozilla.org/browser/session-history-entry;1"].
                   createInstance(Ci.nsISHEntry);
 
-    shEntry.setURI(Utils.makeURI(entry.url, entry.charset));
+    shEntry.setURI(Utils.makeURI(entry.url));
     shEntry.setTitle(entry.title || entry.url);
     if (entry.subframe)
       shEntry.setIsSubFrame(entry.subframe || false);
     shEntry.loadType = Ci.nsIDocShellLoadInfo.loadHistory;
     if (entry.contentType)
       shEntry.contentType = entry.contentType;
     if (entry.referrer) {
       shEntry.referrerURI = Utils.makeURI(entry.referrer);
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -140,26 +140,22 @@ static const char NEVER_ASK_FOR_OPEN_FIL
  * @param aFragment The string to unescape
  * @param aURI The URI from which this fragment is taken. Only its character set
  *             will be used.
  * @param aResult [out] Unescaped string.
  */
 static nsresult UnescapeFragment(const nsACString& aFragment, nsIURI* aURI,
                                  nsAString& aResult)
 {
-  // First, we need a charset
-  nsAutoCString originCharset;
-  nsresult rv = aURI->GetOriginCharset(originCharset);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Now, we need the unescaper
+  // We need the unescaper
+  nsresult rv;
   nsCOMPtr<nsITextToSubURI> textToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return textToSubURI->UnEscapeURIForUI(originCharset, aFragment, aResult);
+  return textToSubURI->UnEscapeURIForUI(NS_LITERAL_CSTRING("UTF-8"), aFragment, aResult);
 }
 
 /**
  * UTF-8 version of UnescapeFragment.
  * @param aFragment The string to unescape
  * @param aURI The URI from which this fragment is taken. Only its character set
  *             will be used.
  * @param aResult [out] Unescaped string, UTF-8 encoded.
--- a/uriloader/exthandler/win/nsMIMEInfoWin.cpp
+++ b/uriloader/exthandler/win/nsMIMEInfoWin.cpp
@@ -222,25 +222,23 @@ nsMIMEInfoWin::LoadUriInternal(nsIURI * 
 
   if (aURL)
   {
     // extract the url spec from the url
     nsAutoCString urlSpec;
     aURL->GetAsciiSpec(urlSpec);
  
     // Unescape non-ASCII characters in the URL
-    nsAutoCString urlCharset;
     nsAutoString utf16Spec;
-    rv = aURL->GetOriginCharset(urlCharset);
-    NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsITextToSubURI> textToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    if (NS_FAILED(textToSubURI->UnEscapeNonAsciiURI(urlCharset, urlSpec, utf16Spec))) {
+    if (NS_FAILED(textToSubURI->UnEscapeNonAsciiURI(NS_LITERAL_CSTRING("UTF-8"),
+                                                    urlSpec, utf16Spec))) {
       CopyASCIItoUTF16(urlSpec, utf16Spec);
     }
 
     static const wchar_t cmdVerb[] = L"open";
     SHELLEXECUTEINFOW sinfo;
     memset(&sinfo, 0, sizeof(sinfo));
     sinfo.cbSize   = sizeof(sinfo);
     sinfo.fMask    = SEE_MASK_FLAG_DDEWAIT |