Bug 1439931 - nsIIOService.extractScheme/net_ExtractURLScheme should lowercase its output draft
authorValentin Gosu <valentin.gosu@gmail.com>
Mon, 26 Feb 2018 16:42:27 +0100
changeset 759759 c94efc1f9d62a79a26ccf50030383ff0ecde30fc
parent 758142 994a684a7564c2735d98d6910a78d079a68f0b25
push id100456
push uservalentin.gosu@gmail.com
push dateMon, 26 Feb 2018 15:43:16 +0000
bugs1439931
milestone60.0a1
Bug 1439931 - nsIIOService.extractScheme/net_ExtractURLScheme should lowercase its output MozReview-Commit-ID: LZ2rqIdIoXQ
browser/base/content/browser.js
docshell/base/nsDefaultURIFixup.cpp
netwerk/base/nsIIOService.idl
netwerk/base/nsSimpleURI.cpp
netwerk/base/nsURLHelper.cpp
netwerk/base/nsURLHelper.h
netwerk/protocol/viewsource/nsViewSourceChannel.cpp
netwerk/test/unit/test_ioservice.js
netwerk/test/unit/xpcshell.ini
toolkit/components/autocomplete/nsAutoCompleteController.cpp
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -6071,17 +6071,17 @@ function middleMousePaste(event) {
 function stripUnsafeProtocolOnPaste(pasteData) {
   // Don't allow pasting javascript URIs since we don't support
   // LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL for those.
   while (true) {
     let scheme = "";
     try {
       scheme = Services.io.extractScheme(pasteData);
     } catch (ex) { }
-    if (scheme.toLowerCase() != "javascript") {
+    if (scheme != "javascript") {
       break;
     }
 
     pasteData = pasteData.substring(pasteData.indexOf(":") + 1);
   }
   return pasteData;
 }
 
--- a/docshell/base/nsDefaultURIFixup.cpp
+++ b/docshell/base/nsDefaultURIFixup.cpp
@@ -157,32 +157,32 @@ nsDefaultURIFixup::GetFixupURIInfo(const
   NS_ENSURE_SUCCESS(rv, rv);
   nsAutoCString scheme;
   ioService->ExtractScheme(aStringURI, scheme);
 
   // View-source is a pseudo scheme. We're interested in fixing up the stuff
   // after it. The easiest way to do that is to call this method again with the
   // "view-source:" lopped off and then prepend it again afterwards.
 
-  if (scheme.LowerCaseEqualsLiteral("view-source")) {
+  if (scheme.EqualsLiteral("view-source")) {
     nsCOMPtr<nsIURIFixupInfo> uriInfo;
     // We disable keyword lookup and alternate URIs so that small typos don't
     // cause us to look at very different domains
     uint32_t newFixupFlags = aFixupFlags & ~FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP
                                          & ~FIXUP_FLAGS_MAKE_ALTERNATE_URI;
 
     const uint32_t viewSourceLen = sizeof("view-source:") - 1;
     nsAutoCString innerURIString(Substring(uriString, viewSourceLen,
                                            uriString.Length() -
                                            viewSourceLen));
     // Prevent recursion:
     innerURIString.Trim(" ");
     nsAutoCString innerScheme;
     ioService->ExtractScheme(innerURIString, innerScheme);
-    if (innerScheme.LowerCaseEqualsLiteral("view-source")) {
+    if (innerScheme.EqualsLiteral("view-source")) {
       return NS_ERROR_FAILURE;
     }
 
     rv = GetFixupURIInfo(innerURIString, newFixupFlags, aPostData,
                          getter_AddRefs(uriInfo));
     if (NS_FAILED(rv)) {
       return NS_ERROR_FAILURE;
     }
@@ -228,57 +228,57 @@ nsDefaultURIFixup::GetFixupURIInfo(const
     MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to observe \"keyword.enabled\"");
     sInitializedPrefCaches = true;
   }
 
   // Fix up common scheme typos.
   if (sFixTypos && (aFixupFlags & FIXUP_FLAG_FIX_SCHEME_TYPOS)) {
     // Fast-path for common cases.
     if (scheme.IsEmpty() ||
-        scheme.LowerCaseEqualsLiteral("http") ||
-        scheme.LowerCaseEqualsLiteral("https") ||
-        scheme.LowerCaseEqualsLiteral("ftp") ||
-        scheme.LowerCaseEqualsLiteral("file")) {
+        scheme.EqualsLiteral("http") ||
+        scheme.EqualsLiteral("https") ||
+        scheme.EqualsLiteral("ftp") ||
+        scheme.EqualsLiteral("file")) {
       // Do nothing.
-    } else if (scheme.LowerCaseEqualsLiteral("ttp")) {
+    } else if (scheme.EqualsLiteral("ttp")) {
       // ttp -> http.
       uriString.ReplaceLiteral(0, 3, "http");
       scheme.AssignLiteral("http");
       info->mFixupChangedProtocol = true;
-    } else if (scheme.LowerCaseEqualsLiteral("htp")) {
+    } else if (scheme.EqualsLiteral("htp")) {
       // htp -> http.
       uriString.ReplaceLiteral(0, 3, "http");
       scheme.AssignLiteral("http");
       info->mFixupChangedProtocol = true;
-    } else if (scheme.LowerCaseEqualsLiteral("ttps")) {
+    } else if (scheme.EqualsLiteral("ttps")) {
       // ttps -> https.
       uriString.ReplaceLiteral(0, 4, "https");
       scheme.AssignLiteral("https");
       info->mFixupChangedProtocol = true;
-    } else if (scheme.LowerCaseEqualsLiteral("tps")) {
+    } else if (scheme.EqualsLiteral("tps")) {
       // tps -> https.
       uriString.ReplaceLiteral(0, 3, "https");
       scheme.AssignLiteral("https");
       info->mFixupChangedProtocol = true;
-    } else if (scheme.LowerCaseEqualsLiteral("ps")) {
+    } else if (scheme.EqualsLiteral("ps")) {
       // ps -> https.
       uriString.ReplaceLiteral(0, 2, "https");
       scheme.AssignLiteral("https");
       info->mFixupChangedProtocol = true;
-    } else if (scheme.LowerCaseEqualsLiteral("htps")) {
+    } else if (scheme.EqualsLiteral("htps")) {
       // htps -> https.
       uriString.ReplaceLiteral(0, 4, "https");
       scheme.AssignLiteral("https");
       info->mFixupChangedProtocol = true;
-    } else if (scheme.LowerCaseEqualsLiteral("ile")) {
+    } else if (scheme.EqualsLiteral("ile")) {
       // ile -> file.
       uriString.ReplaceLiteral(0, 3, "file");
       scheme.AssignLiteral("file");
       info->mFixupChangedProtocol = true;
-    } else if (scheme.LowerCaseEqualsLiteral("le")) {
+    } else if (scheme.EqualsLiteral("le")) {
       // le -> file.
       uriString.ReplaceLiteral(0, 2, "file");
       scheme.AssignLiteral("file");
       info->mFixupChangedProtocol = true;
     }
   }
 
   // Now we need to check whether "scheme" is something we don't
--- a/netwerk/base/nsIIOService.idl
+++ b/netwerk/base/nsIIOService.idl
@@ -191,17 +191,17 @@ interface nsIIOService : nsISupports
      * Utility to extract the scheme from a URL string, consistently and
      * according to spec (see RFC 2396).
      *
      * NOTE: Most URL parsing is done via nsIURI, and in fact the scheme
      * can also be extracted from a URL string via nsIURI.  This method
      * is provided purely as an optimization.
      *
      * @param aSpec the URL string to parse
-     * @return URL scheme
+     * @return URL scheme, lowercase
      *
      * @throws NS_ERROR_MALFORMED_URI if URL string is not of the right form.
      */
     ACString extractScheme(in AUTF8String urlString);
 
     /**
      * Checks if a URI host is a local IPv4 or IPv6 address literal.
      *
--- a/netwerk/base/nsSimpleURI.cpp
+++ b/netwerk/base/nsSimpleURI.cpp
@@ -291,17 +291,16 @@ nsresult
 nsSimpleURI::SetSpecInternal(const nsACString &aSpec)
 {
     NS_ENSURE_STATE(mMutable);
 
     nsresult rv = net_ExtractURLScheme(aSpec, mScheme);
     if (NS_FAILED(rv)) {
         return rv;
     }
-    ToLowerCase(mScheme);
 
     nsAutoCString spec;
     rv = net_FilterAndEscapeURI(aSpec, esc_OnlyNonASCII, spec);
     if (NS_FAILED(rv)) {
         return rv;
     }
 
     int32_t colonPos = spec.FindChar(':');
--- a/netwerk/base/nsURLHelper.cpp
+++ b/netwerk/base/nsURLHelper.cpp
@@ -520,16 +520,17 @@ net_ExtractURLScheme(const nsACString &i
     }
 
     if (!p.CheckChar(':')) {
         return NS_ERROR_MALFORMED_URI;
     }
 
     p.Claim(scheme);
     scheme.StripTaggedASCII(ASCIIMask::MaskCRLFTab());
+    ToLowerCase(scheme);
     return NS_OK;
 }
 
 bool
 net_IsValidScheme(const char *scheme, uint32_t schemeLen)
 {
     // first char must be alpha
     if (!nsCRT::IsAsciiAlpha(*scheme))
--- a/netwerk/base/nsURLHelper.h
+++ b/netwerk/base/nsURLHelper.h
@@ -86,17 +86,17 @@ nsresult net_ResolveRelativePath(const n
  * @return true if the given spec represents an absolute URL
  */
 bool net_IsAbsoluteURL(const nsACString& inURL);
 
 /**
  * Extract URI-Scheme if possible
  *
  * @param inURI     URI spec
- * @param scheme    scheme copied to this buffer on return (may be null)
+ * @param scheme    scheme copied to this buffer on return. Is lowercase.
  */
 nsresult net_ExtractURLScheme(const nsACString &inURI,
                               nsACString &scheme);
 
 /* check that the given scheme conforms to RFC 2396 */
 bool net_IsValidScheme(const char *scheme, uint32_t schemeLen);
 
 inline bool net_IsValidScheme(const nsCString& scheme)
--- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
+++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
@@ -52,17 +52,17 @@ nsViewSourceChannel::Init(nsIURI* uri)
     if (NS_FAILED(rv)) return rv;
 
     nsAutoCString scheme;
     rv = pService->ExtractScheme(path, scheme);
     if (NS_FAILED(rv))
       return rv;
 
     // prevent viewing source of javascript URIs (see bug 204779)
-    if (scheme.LowerCaseEqualsLiteral("javascript")) {
+    if (scheme.EqualsLiteral("javascript")) {
       NS_WARNING("blocking view-source:javascript:");
       return NS_ERROR_INVALID_ARG;
     }
 
     // This function is called from within nsViewSourceHandler::NewChannel2
     // and sets the right loadInfo right after returning from this function.
     // Until then we follow the principal of least privilege and use
     // nullPrincipal as the loadingPrincipal and the least permissive
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_ioservice.js
@@ -0,0 +1,11 @@
+"use strict";
+
+ChromeUtils.import('resource://gre/modules/Services.jsm');
+
+add_task(function test_extractScheme(){
+  equal(Services.io.extractScheme("HtTp://example.com"), "http");
+  Assert.throws(() => { Services.io.extractScheme("://example.com"); },
+                /NS_ERROR_MALFORMED_URI/, "missing scheme");
+  Assert.throws(() => { Services.io.extractScheme("ht%tp://example.com"); },
+                /NS_ERROR_MALFORMED_URI/, "bad scheme");
+});
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -410,8 +410,9 @@ skip-if = os == "android"
 [test_tls_flags_separate_connections.js]
 [test_tls_flags.js]
 [test_uri_mutator.js]
 [test_bug1411316_http1.js]
 [test_header_Server_Timing.js]
 [test_trr.js]
 # http2-using tests require node available
 skip-if = os == "android"
+[test_ioservice.js]
--- a/toolkit/components/autocomplete/nsAutoCompleteController.cpp
+++ b/toolkit/components/autocomplete/nsAutoCompleteController.cpp
@@ -1675,17 +1675,17 @@ nsAutoCompleteController::CompleteValue(
     if (NS_SUCCEEDED(ios->ExtractScheme(NS_ConvertUTF16toUTF8(aValue), scheme))) {
       // Trying to autocomplete a URI from somewhere other than the beginning.
       // Only succeed if the missing portion is "http://"; otherwise do not
       // autocomplete.  This prevents us from "helpfully" autocompleting to a
       // URI that isn't equivalent to what the user expected.
       const int32_t findIndex = 7; // length of "http://"
 
       if ((endSelect < findIndex + mSearchStringLength) ||
-          !scheme.LowerCaseEqualsLiteral("http") ||
+          !scheme.EqualsLiteral("http") ||
           !Substring(aValue, findIndex, mSearchStringLength).Equals(
             mSearchString, nsCaseInsensitiveStringComparator())) {
         return NS_OK;
       }
 
       mPlaceholderCompletionString = mSearchString +
         Substring(aValue, mSearchStringLength + findIndex, endSelect);
       SetValueOfInputTo(