Bug 1497301 part 4. Simplify Location::CheckURL. r=bholley
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 12 Oct 2018 11:07:18 -0400
changeset 499882 90b73f4b4635a692c5528a0703b0e9bb5355caac
parent 499881 08174b4a8022f1a0b29bacb9d8f3a247e1497042
child 499883 4700f0a79ebd4ec48932225cc7c124c999656938
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1497301
milestone64.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 1497301 part 4. Simplify Location::CheckURL. r=bholley The main change is to just use the principal bindings pass us to do our CheckLoadURI check. If we do that, we don't have to care about the current JSContext.
dom/base/Location.cpp
dom/base/Location.h
dom/bindings/Errors.msg
dom/webidl/Location.webidl
testing/web-platform/meta/url/failure.html.ini
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -56,117 +56,117 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Location, mInnerWindow)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Location)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Location)
 
-nsresult
-Location::CheckURL(nsIURI* aURI, nsDocShellLoadInfo** aLoadInfo)
+already_AddRefed<nsDocShellLoadInfo>
+Location::CheckURL(nsIURI* aURI, nsIPrincipal& aSubjectPrincipal,
+                   ErrorResult& aRv)
 {
-  *aLoadInfo = nullptr;
-
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
-  NS_ENSURE_TRUE(docShell, NS_ERROR_NOT_AVAILABLE);
+  if (NS_WARN_IF(!docShell)) {
+    aRv.Throw(NS_ERROR_NOT_AVAILABLE);
+    return nullptr;
+  }
 
   nsCOMPtr<nsIPrincipal> triggeringPrincipal;
   nsCOMPtr<nsIURI> sourceURI;
   net::ReferrerPolicy referrerPolicy = net::RP_Unset;
 
-  if (JSContext *cx = nsContentUtils::GetCurrentJSContext()) {
-    // No cx means that there's no JS running, or at least no JS that
-    // was run through code that properly pushed a context onto the
-    // context stack (as all code that runs JS off of web pages
-    // does). We won't bother with security checks in this case, but
-    // we need to create the loadinfo etc.
-
-    // Get security manager.
-    nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
-    NS_ENSURE_STATE(ssm);
-
-    // Check to see if URI is allowed.
-    nsresult rv = ssm->CheckLoadURIFromScript(cx, aURI);
-    NS_ENSURE_SUCCESS(rv, rv);
+  // Get security manager.
+  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
+  if (NS_WARN_IF(!ssm)) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
 
-    // Make the load's referrer reflect changes to the document's URI caused by
-    // push/replaceState, if possible.  First, get the document corresponding to
-    // fp.  If the document's original URI (i.e. its URI before
-    // push/replaceState) matches the principal's URI, use the document's
-    // current URI as the referrer.  If they don't match, use the principal's
-    // URI.
-    //
-    // The triggering principal for this load should be the principal of the
-    // incumbent document (which matches where the referrer information is
-    // coming from) when there is an incumbent document, and the subject
-    // principal otherwise.  Note that the URI in the triggering principal
-    // may not match the referrer URI in various cases, notably including
-    // the cases when the incumbent document's document URI was modified
-    // after the document was loaded.
+  // Check to see if URI is allowed.
+  nsresult rv = ssm->CheckLoadURIWithPrincipal(&aSubjectPrincipal, aURI,
+                                               nsIScriptSecurityManager::STANDARD);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    nsAutoCString spec;
+    aURI->GetSpec(spec);
+    aRv.ThrowTypeError<MSG_URL_NOT_LOADABLE>(NS_ConvertUTF8toUTF16(spec));
+    return nullptr;
+  }
+
+  // Make the load's referrer reflect changes to the document's URI caused by
+  // push/replaceState, if possible.  First, get the document corresponding to
+  // fp.  If the document's original URI (i.e. its URI before
+  // push/replaceState) matches the principal's URI, use the document's
+  // current URI as the referrer.  If they don't match, use the principal's
+  // URI.
+  //
+  // The triggering principal for this load should be the principal of the
+  // incumbent document (which matches where the referrer information is
+  // coming from) when there is an incumbent document, and the subject
+  // principal otherwise.  Note that the URI in the triggering principal
+  // may not match the referrer URI in various cases, notably including
+  // the cases when the incumbent document's document URI was modified
+  // after the document was loaded.
 
-    nsCOMPtr<nsPIDOMWindowInner> incumbent =
-      do_QueryInterface(mozilla::dom::GetIncumbentGlobal());
-    nsCOMPtr<nsIDocument> doc = incumbent ? incumbent->GetDoc() : nullptr;
+  nsCOMPtr<nsPIDOMWindowInner> incumbent =
+    do_QueryInterface(mozilla::dom::GetIncumbentGlobal());
+  nsCOMPtr<nsIDocument> doc = incumbent ? incumbent->GetDoc() : nullptr;
 
-    if (doc) {
-      nsCOMPtr<nsIURI> docOriginalURI, docCurrentURI, principalURI;
-      docOriginalURI = doc->GetOriginalURI();
-      docCurrentURI = doc->GetDocumentURI();
-      rv = doc->NodePrincipal()->GetURI(getter_AddRefs(principalURI));
-      NS_ENSURE_SUCCESS(rv, rv);
+  if (doc) {
+    nsCOMPtr<nsIURI> docOriginalURI, docCurrentURI, principalURI;
+    docOriginalURI = doc->GetOriginalURI();
+    docCurrentURI = doc->GetDocumentURI();
+    rv = doc->NodePrincipal()->GetURI(getter_AddRefs(principalURI));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      aRv.Throw(rv);
+      return nullptr;
+    }
 
-      triggeringPrincipal = doc->NodePrincipal();
-      referrerPolicy = doc->GetReferrerPolicy();
+    triggeringPrincipal = doc->NodePrincipal();
+    referrerPolicy = doc->GetReferrerPolicy();
 
-      bool urisEqual = false;
-      if (docOriginalURI && docCurrentURI && principalURI) {
-        principalURI->Equals(docOriginalURI, &urisEqual);
-      }
-      if (urisEqual) {
-        sourceURI = docCurrentURI;
-      }
-      else {
-        // Use principalURI as long as it is not an NullPrincipalURI.  We
-        // could add a method such as GetReferrerURI to principals to make this
-        // cleaner, but given that we need to start using Source Browsing
-        // Context for referrer (see Bug 960639) this may be wasted effort at
-        // this stage.
-        if (principalURI) {
-          bool isNullPrincipalScheme;
-          rv = principalURI->SchemeIs(NS_NULLPRINCIPAL_SCHEME,
-                                     &isNullPrincipalScheme);
-          if (NS_SUCCEEDED(rv) && !isNullPrincipalScheme) {
-            sourceURI = principalURI;
-          }
+    bool urisEqual = false;
+    if (docOriginalURI && docCurrentURI && principalURI) {
+      principalURI->Equals(docOriginalURI, &urisEqual);
+    }
+    if (urisEqual) {
+      sourceURI = docCurrentURI;
+    }
+    else {
+      // Use principalURI as long as it is not an NullPrincipalURI.  We
+      // could add a method such as GetReferrerURI to principals to make this
+      // cleaner, but given that we need to start using Source Browsing
+      // Context for referrer (see Bug 960639) this may be wasted effort at
+      // this stage.
+      if (principalURI) {
+        bool isNullPrincipalScheme;
+        rv = principalURI->SchemeIs(NS_NULLPRINCIPAL_SCHEME,
+                                    &isNullPrincipalScheme);
+        if (NS_SUCCEEDED(rv) && !isNullPrincipalScheme) {
+          sourceURI = principalURI;
         }
       }
     }
-    else {
-      // No document; determine triggeringPrincipal by quering the
-      // subjectPrincipal, wich is the principal of the current JS
-      // compartment, or a null principal in case there is no
-      // compartment yet.
-      triggeringPrincipal = nsContentUtils::SubjectPrincipal();
-    }
+  } else {
+    // No document; just use our subject principal as the triggering principal.
+    triggeringPrincipal = &aSubjectPrincipal;
   }
 
   // Create load info
   RefPtr<nsDocShellLoadInfo> loadInfo = new nsDocShellLoadInfo();
 
   loadInfo->SetTriggeringPrincipal(triggeringPrincipal);
 
   if (sourceURI) {
     loadInfo->SetReferrer(sourceURI);
     loadInfo->SetReferrerPolicy(referrerPolicy);
   }
 
-  loadInfo.swap(*aLoadInfo);
-
-  return NS_OK;
+  return loadInfo.forget();
 }
 
 nsresult
 Location::GetURI(nsIURI** aURI, bool aGetInnermostURI)
 {
   *aURI = nullptr;
 
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
@@ -202,24 +202,24 @@ Location::GetURI(nsIURI** aURI, bool aGe
 
   nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return urifixup->CreateExposableURI(uri, aURI);
 }
 
 void
-Location::SetURI(nsIURI* aURI, ErrorResult& aRv, bool aReplace)
+Location::SetURI(nsIURI* aURI, nsIPrincipal& aSubjectPrincipal,
+                 ErrorResult& aRv, bool aReplace)
 {
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
   if (docShell) {
-    RefPtr<nsDocShellLoadInfo> loadInfo;
-
-    if (NS_FAILED(CheckURL(aURI, getter_AddRefs(loadInfo)))) {
-      aRv.Throw(NS_ERROR_FAILURE);
+    RefPtr<nsDocShellLoadInfo> loadInfo =
+      CheckURL(aURI, aSubjectPrincipal, aRv);
+    if (aRv.Failed()) {
       return;
     }
 
     if (aReplace) {
       loadInfo->SetLoadType(LOAD_STOP_CONTENT_AND_REPLACE);
     } else {
       loadInfo->SetLoadType(LOAD_STOP_CONTENT);
     }
@@ -303,17 +303,17 @@ Location::SetHash(const nsAString& aHash
 
   aRv = NS_MutateURI(uri)
           .SetRef(hash)
           .Finalize(uri);
   if (NS_WARN_IF(aRv.Failed()) || !uri) {
     return;
   }
 
-  SetURI(uri, aRv);
+  SetURI(uri, aSubjectPrincipal, aRv);
 }
 
 void
 Location::GetHost(nsAString& aHost,
                   nsIPrincipal& aSubjectPrincipal,
                   ErrorResult& aRv)
 {
   if (!CallerSubsumes(&aSubjectPrincipal)) {
@@ -357,17 +357,17 @@ Location::SetHost(const nsAString& aHost
 
   aRv = NS_MutateURI(uri)
           .SetHostPort(NS_ConvertUTF16toUTF8(aHost))
           .Finalize(uri);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
-  SetURI(uri, aRv);
+  SetURI(uri, aSubjectPrincipal, aRv);
 }
 
 void
 Location::GetHostname(nsAString& aHostname,
                       nsIPrincipal& aSubjectPrincipal,
                       ErrorResult& aRv)
 {
   if (!CallerSubsumes(&aSubjectPrincipal)) {
@@ -402,17 +402,17 @@ Location::SetHostname(const nsAString& a
 
   aRv = NS_MutateURI(uri)
           .SetHost(NS_ConvertUTF16toUTF8(aHostname))
           .Finalize(uri);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
-  SetURI(uri, aRv);
+  SetURI(uri, aSubjectPrincipal, aRv);
 }
 
 nsresult
 Location::GetHref(nsAString& aHref)
 {
   aHref.Truncate();
 
   nsCOMPtr<nsIURI> uri;
@@ -428,31 +428,34 @@ Location::GetHref(nsAString& aHref)
   }
 
   AppendUTF8toUTF16(uriString, aHref);
   return NS_OK;
 }
 
 void
 Location::SetHref(const nsAString& aHref,
+                  nsIPrincipal& aSubjectPrincipal,
                   ErrorResult& aRv)
 {
-  DoSetHref(aHref, false, aRv);
+  DoSetHref(aHref, aSubjectPrincipal, false, aRv);
 }
 
 void
-Location::DoSetHref(const nsAString& aHref, bool aReplace, ErrorResult& aRv)
+Location::DoSetHref(const nsAString& aHref, nsIPrincipal& aSubjectPrincipal,
+                    bool aReplace, ErrorResult& aRv)
 {
   // Get the source of the caller
   nsCOMPtr<nsIURI> base = GetSourceBaseURL();
-  SetHrefWithBase(aHref, base, aReplace, aRv);
+  SetHrefWithBase(aHref, base, aSubjectPrincipal, aReplace, aRv);
 }
 
 void
 Location::SetHrefWithBase(const nsAString& aHref, nsIURI* aBase,
+                          nsIPrincipal& aSubjectPrincipal,
                           bool aReplace, ErrorResult& aRv)
 {
   nsresult result;
   nsCOMPtr<nsIURI> newUri;
 
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
 
   if (nsIDocument* doc = GetEntryDocument()) {
@@ -485,17 +488,17 @@ Location::SetHrefWithBase(const nsAStrin
         // since we only want to replace if the location is set by a
         // <script> tag in the same window.  See bug 178729.
         nsCOMPtr<nsIScriptGlobalObject> ourGlobal =
           docShell ? docShell->GetScriptGlobalObject() : nullptr;
         inScriptTag = (ourGlobal == scriptContext->GetGlobalObject());
       }
     }
 
-    SetURI(newUri, aRv, aReplace || inScriptTag);
+    SetURI(newUri, aSubjectPrincipal, aRv, aReplace || inScriptTag);
     return;
   }
 
   aRv.Throw(result);
 }
 
 void
 Location::GetOrigin(nsAString& aOrigin,
@@ -570,17 +573,17 @@ Location::SetPathname(const nsAString& a
 
   nsresult rv = NS_MutateURI(uri)
                   .SetFilePath(NS_ConvertUTF16toUTF8(aPathname))
                   .Finalize(uri);
   if (NS_FAILED(rv)) {
     return;
   }
 
-  SetURI(uri, aRv);
+  SetURI(uri, aSubjectPrincipal, aRv);
 }
 
 void
 Location::GetPort(nsAString& aPort,
                   nsIPrincipal& aSubjectPrincipal,
                   ErrorResult& aRv)
 {
   if (!CallerSubsumes(&aSubjectPrincipal)) {
@@ -639,17 +642,17 @@ Location::SetPort(const nsAString& aPort
 
   aRv = NS_MutateURI(uri)
           .SetPort(port)
           .Finalize(uri);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
-  SetURI(uri, aRv);
+  SetURI(uri, aSubjectPrincipal, aRv);
 }
 
 void
 Location::GetProtocol(nsAString& aProtocol,
                       nsIPrincipal& aSubjectPrincipal,
                       ErrorResult& aRv)
 {
   if (!CallerSubsumes(&aSubjectPrincipal)) {
@@ -736,17 +739,17 @@ Location::SetProtocol(const nsAString& a
     return;
   }
 
   if (!isHttp && !isHttps) {
     // No-op, per spec.
     return;
   }
 
-  SetURI(uri, aRv);
+  SetURI(uri, aSubjectPrincipal, aRv);
 }
 
 void
 Location::GetSearch(nsAString& aSearch,
                     nsIPrincipal& aSubjectPrincipal,
                     ErrorResult& aRv)
 {
   if (!CallerSubsumes(&aSubjectPrincipal)) {
@@ -801,17 +804,17 @@ Location::SetSearch(const nsAString& aSe
     aRv = NS_MutateURI(uri)
             .SetQuery(NS_ConvertUTF16toUTF8(aSearch))
             .Finalize(uri);
   }
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
-  SetURI(uri, aRv);
+  SetURI(uri, aSubjectPrincipal, aRv);
 }
 
 nsresult
 Location::Reload(bool aForceget)
 {
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
   nsCOMPtr<nsPIDOMWindowOuter> window = docShell ? docShell->GetWindow()
@@ -857,30 +860,30 @@ Location::Reload(bool aForceget)
   return rv;
 }
 
 void
 Location::Replace(const nsAString& aUrl,
                   nsIPrincipal& aSubjectPrincipal,
                   ErrorResult& aRv)
 {
-  DoSetHref(aUrl, true, aRv);
+  DoSetHref(aUrl, aSubjectPrincipal, true, aRv);
 }
 
 void
 Location::Assign(const nsAString& aUrl,
                  nsIPrincipal& aSubjectPrincipal,
                  ErrorResult& aRv)
 {
   if (!CallerSubsumes(&aSubjectPrincipal)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
-  DoSetHref(aUrl, false, aRv);
+  DoSetHref(aUrl, aSubjectPrincipal, false, aRv);
 }
 
 already_AddRefed<nsIURI>
 Location::GetSourceBaseURL()
 {
   nsIDocument* doc = GetEntryDocument();
   // If there's no entry document, we either have no Script Entry Point or one
   // that isn't a DOM Window.  This doesn't generally happen with the DOM, but
--- a/dom/base/Location.h
+++ b/dom/base/Location.h
@@ -63,16 +63,17 @@ public:
       aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
       return;
     }
 
     aError = GetHref(aHref);
   }
 
   void SetHref(const nsAString& aHref,
+               nsIPrincipal& aSubjectPrincipal,
                ErrorResult& aError);
 
   void GetOrigin(nsAString& aOrigin,
                  nsIPrincipal& aSubjectPrincipal,
                  ErrorResult& aError);
 
   void GetProtocol(nsAString& aProtocol,
                    nsIPrincipal& aSubjectPrincipal,
@@ -161,27 +162,37 @@ protected:
   virtual ~Location();
 
   // In the case of jar: uris, we sometimes want the place the jar was
   // fetched from as the URI instead of the jar: uri itself.  Pass in
   // true for aGetInnermostURI when that's the case.
   // Note, this method can return NS_OK with a null value for aURL. This happens
   // if the docShell is null.
   nsresult GetURI(nsIURI** aURL, bool aGetInnermostURI = false);
-  void SetURI(nsIURI* aURL, ErrorResult& aRv, bool aReplace = false);
+  void SetURI(nsIURI* aURL, nsIPrincipal& aSubjectPrincipal,
+              ErrorResult& aRv, bool aReplace = false);
   void SetHrefWithBase(const nsAString& aHref, nsIURI* aBase,
+                       nsIPrincipal& aSubjectPrincipal,
                        bool aReplace, ErrorResult& aRv);
 
   // Helper for Assign/SetHref/Replace
-  void DoSetHref(const nsAString& aHref, bool aReplace, ErrorResult& aRv);
+  void DoSetHref(const nsAString& aHref, nsIPrincipal& aSubjectPrincipal,
+                 bool aReplace, ErrorResult& aRv);
 
   // Get the base URL we should be using for our relative URL
   // resolution for SetHref/Assign/Replace.
   already_AddRefed<nsIURI> GetSourceBaseURL();
-  nsresult CheckURL(nsIURI *url, nsDocShellLoadInfo** aLoadInfo);
+
+  // Check whether it's OK to load the given url with the given subject
+  // principal, and if so construct the right nsDocShellLoadInfo for the load
+  // and return it.
+  already_AddRefed<nsDocShellLoadInfo> CheckURL(nsIURI *url,
+                                                nsIPrincipal& aSubjectPrincipal,
+                                                ErrorResult& aRv);
+
   bool CallerSubsumes(nsIPrincipal* aSubjectPrincipal);
 
   nsString mCachedHash;
   nsCOMPtr<nsPIDOMWindowInner> mInnerWindow;
   nsWeakPtr mDocShell;
 };
 
 } // dom namespace
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -111,8 +111,9 @@ MSG_DEF(MSG_INVALID_AUDIOPARAM_METHOD_ST
 MSG_DEF(MSG_INVALID_AUDIOPARAM_METHOD_END_TIME_ERROR, 0, JSEXN_RANGEERR, "The end time for an AudioParam method must be non-negative.")
 MSG_DEF(MSG_INVALID_AUDIOPARAM_EXPONENTIAL_VALUE_ERROR, 0, JSEXN_RANGEERR, "The value passed to exponentialRampToValueAtTime must be positive.")
 MSG_DEF(MSG_INVALID_AUDIOPARAM_EXPONENTIAL_CONSTANT_ERROR, 0, JSEXN_RANGEERR, "The exponential constant passed to setTargetAtTime must be non-negative.")
 MSG_DEF(MSG_VALUE_OUT_OF_RANGE, 1, JSEXN_RANGEERR, "The value for the {0} is outside the valid range.")
 MSG_DEF(MSG_INVALID_PANNERNODE_REFDISTANCE_ERROR, 0, JSEXN_RANGEERR, "The refDistance value passed to PannerNode must not be negative.")
 MSG_DEF(MSG_INVALID_PANNERNODE_MAXDISTANCE_ERROR, 0, JSEXN_RANGEERR, "The maxDistance value passed to PannerNode must be positive.")
 MSG_DEF(MSG_INVALID_PANNERNODE_ROLLOFF_ERROR, 0, JSEXN_RANGEERR, "The rolloffFactor value passed to PannerNode must not be negative.")
 MSG_DEF(MSG_NOT_ARRAY_NOR_UNDEFINED, 1, JSEXN_TYPEERR, "{0} is neither an array nor undefined.")
+MSG_DEF(MSG_URL_NOT_LOADABLE, 1, JSEXN_TYPEERR, "Access to '{0}' from script denied.")
--- a/dom/webidl/Location.webidl
+++ b/dom/webidl/Location.webidl
@@ -15,17 +15,17 @@
 interface Location {
   // Bug 824857: no support for stringifier attributes yet.
   //  stringifier attribute USVString href;
 
   // Bug 824857 should remove this.
   [Throws, NeedsSubjectPrincipal]
   stringifier;
 
-  [Throws, CrossOriginWritable, GetterNeedsSubjectPrincipal]
+  [Throws, CrossOriginWritable, NeedsSubjectPrincipal]
            attribute USVString href;
   [Throws, NeedsSubjectPrincipal]
   readonly attribute USVString origin;
   [Throws, NeedsSubjectPrincipal]
            attribute USVString protocol;
   [Throws, NeedsSubjectPrincipal]
            attribute USVString host;
   [Throws, NeedsSubjectPrincipal]
--- a/testing/web-platform/meta/url/failure.html.ini
+++ b/testing/web-platform/meta/url/failure.html.ini
@@ -1,45 +1,33 @@
 [failure.html]
   [URL's href: file://example:1/ should throw]
     expected: FAIL
 
   [XHR: file://example:1/ should throw]
     expected: FAIL
 
-  [Location's href: file://example:1/ should throw]
-    expected: FAIL
-
   [URL's href: file://example:test/ should throw]
     expected: FAIL
 
   [XHR: file://example:test/ should throw]
     expected: FAIL
 
-  [Location's href: file://example:test/ should throw]
-    expected: FAIL
-
   [URL's href: file://example%/ should throw]
     expected: FAIL
 
   [XHR: file://example%/ should throw]
     expected: FAIL
 
-  [Location's href: file://example%/ should throw]
-    expected: FAIL
-
   [URL's href: file://[example\]/ should throw]
     expected: FAIL
 
   [XHR: file://[example\]/ should throw]
     expected: FAIL
 
-  [Location's href: file://[example\]/ should throw]
-    expected: FAIL
-
   [Location's href: http://user:pass@/ should throw]
     expected: FAIL
 
   [Location's href: http://foo:-80/ should throw]
     expected: FAIL
 
   [XHR: http:/:@/www.example.com should throw]
     expected: FAIL