Bug 1328894 part 2. Strip ':' and anything following it from the string passed to the location.protocol setter. r=bkelly
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 08 Feb 2017 18:19:02 -0500
changeset 341398 7ebd23243cdf2a1e6bffabaacf0818d70e5fedc9
parent 341397 1d229f56d3baae59cd38c3e0d0259f0a2af80d65
child 341399 28e96f6befceda3ebcb0f2ad6068f61900013fa6
push id86724
push userbzbarsky@mozilla.com
push dateWed, 08 Feb 2017 23:19:17 +0000
treeherdermozilla-inbound@28e96f6befce [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbkelly
bugs1328894
milestone54.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 1328894 part 2. Strip ':' and anything following it from the string passed to the location.protocol setter. r=bkelly
dom/base/Location.cpp
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/html/browsers/history/the-location-interface/location-protocol-setter-with-colon.sub.html
testing/web-platform/tests/html/browsers/history/the-location-interface/resources/post-your-protocol.html
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -28,16 +28,17 @@
 #include "nsITextToSubURI.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "mozilla/Likely.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsNullPrincipal.h"
 #include "ScriptSettings.h"
+#include "mozilla/Unused.h"
 #include "mozilla/dom/LocationBinding.h"
 
 namespace mozilla {
 namespace dom {
 
 static nsresult
 GetDocumentCharacterSetForURI(const nsAString& aHref, nsACString& aCharset)
 {
@@ -694,17 +695,23 @@ NS_IMETHODIMP
 Location::SetProtocol(const nsAString& aProtocol)
 {
   nsCOMPtr<nsIURI> uri;
   nsresult rv = GetWritableURI(getter_AddRefs(uri));
   if (NS_WARN_IF(NS_FAILED(rv) || !uri)) {
     return rv;
   }
 
-  rv = uri->SetScheme(NS_ConvertUTF16toUTF8(aProtocol));
+  nsAString::const_iterator start, end;
+  aProtocol.BeginReading(start);
+  aProtocol.EndReading(end);
+  nsAString::const_iterator iter(start);
+  Unused << FindCharInReadable(':', iter, end);
+
+  rv = uri->SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter)));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   nsAutoCString newSpec;
   rv = uri->GetSpec(newSpec);
   if (NS_FAILED(rv)) {
     return rv;
   }
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -44716,16 +44716,21 @@
      {}
     ]
    ],
    "html/browsers/history/the-location-interface/reload_post_1-1.html": [
     [
      {}
     ]
    ],
+   "html/browsers/history/the-location-interface/resources/post-your-protocol.html": [
+    [
+     {}
+    ]
+   ],
    "html/browsers/history/the-location-interface/same_origin_frame.html": [
     [
      {}
     ]
    ],
    "html/browsers/history/the-location-interface/scripted_click_assign_during_load-1.html": [
     [
      {}
@@ -88153,16 +88158,22 @@
     ]
    ],
    "html/browsers/history/the-location-interface/location-protocol-setter-non-broken.html": [
     [
      "/html/browsers/history/the-location-interface/location-protocol-setter-non-broken.html",
      {}
     ]
    ],
+   "html/browsers/history/the-location-interface/location-protocol-setter-with-colon.sub.html": [
+    [
+     "/html/browsers/history/the-location-interface/location-protocol-setter-with-colon.sub.html",
+     {}
+    ]
+   ],
    "html/browsers/history/the-location-interface/location-protocol-setter.html": [
     [
      "/html/browsers/history/the-location-interface/location-protocol-setter.html",
      {}
     ]
    ],
    "html/browsers/history/the-location-interface/location-prototype-setting.html": [
     [
@@ -164904,16 +164915,20 @@
   "html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird.html": [
    "13a360b3010a85c1661d9357355894453137c9df",
    "testharness"
   ],
   "html/browsers/history/the-location-interface/location-protocol-setter-non-broken.html": [
    "bc622cdff29f6d8369d7bd07036bb220ea5774de",
    "testharness"
   ],
+  "html/browsers/history/the-location-interface/location-protocol-setter-with-colon.sub.html": [
+   "713e4cc9f9cee9830176bb481da52699fff56bbc",
+   "testharness"
+  ],
   "html/browsers/history/the-location-interface/location-protocol-setter.html": [
    "70f3c81ddfe58e8751543513fbd8ea44a6b122a1",
    "testharness"
   ],
   "html/browsers/history/the-location-interface/location-prototype-setting.html": [
    "47a284185d6abb33d601a3b066a72bf480b515e7",
    "testharness"
   ],
@@ -165056,16 +165071,20 @@
   "html/browsers/history/the-location-interface/reload_post_1-1.html": [
    "656f35b990b49ec854580bcaa860e718e463a0e4",
    "support"
   ],
   "html/browsers/history/the-location-interface/reload_post_1.html": [
    "3f86c065f9ea20c9b9a0c6fd2f0fd94ae73f3088",
    "testharness"
   ],
+  "html/browsers/history/the-location-interface/resources/post-your-protocol.html": [
+   "d6a54e137ca516d16fb64bed157b0ac3ceaab99c",
+   "support"
+  ],
   "html/browsers/history/the-location-interface/same_origin_frame.html": [
    "ffabc8fb608c6dad4e7d1d148a4d77cdc4231e68",
    "support"
   ],
   "html/browsers/history/the-location-interface/scripted_click_assign_during_load-1.html": [
    "fbf272408fb3abec6867a67e309ecfba36e51b24",
    "support"
   ],
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-protocol-setter-with-colon.sub.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<iframe id="existing" src="resources/post-your-protocol.html?existing"></iframe>
+<iframe id="http-and-gunk" src="resources/post-your-protocol.html?http-and-gunk"></iframe>
+<iframe id="https-and-gunk" src="resources/post-your-protocol.html?https-and-gunk"></iframe>
+<script>
+// NOTE: we do not listen to message events until our load event fires, so we
+// only get them for the things we actually care about.
+var wrapper_test = async_test("General setup");
+var tests = {
+  "existing": { test: async_test("Set location.protocol = location.protocol"),
+                result: location.protocol },
+  "http-and-gunk": { test:  async_test("Set location.protocol to http:gunk"),
+                     result: "http:" },
+  // We should really test the "https:gunk" case too, and assert that it ends up
+  // with a protocol of "https:", but can't.  See comments below for why.
+};
+
+function messageListener(e) {
+  test(function() {
+    var data = e.data;
+    var id = data.id;
+    var t = tests[id].test;
+    t.step(function() {
+      assert_equals(data.protocol, tests[id].result, "Protocol should match");
+    })
+    t.done();
+  }, "Message listener");
+}
+
+addEventListener("load", wrapper_test.step_func_done(function() {
+  addEventListener("message", messageListener);
+
+  tests["existing"].test.step(function() {
+    var loc = document.getElementById("existing").contentWindow.location;
+    loc.protocol = loc.protocol;
+  });
+  tests["http-and-gunk"].test.step(function() {
+    var loc = document.getElementById("http-and-gunk").contentWindow.location;
+    loc.protocol = "http:gunk";
+  });
+  // I wish we could test the https bit, but can't figure out a non-racy way to
+  // do it, because we need to change both protocol (to https) _and_ port to
+  // {{ports[https][0]}} to get a successful load unless we're running on the
+  // default http port, but the setter uses the current value, which doesn't get
+  // updated sync, as the url to start with for the set.  Oh, and there's no
+  // good way to detect when the port set is "done" either.
+}));
+
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/post-your-protocol.html
@@ -0,0 +1,4 @@
+<script>
+  var id = location.search.substring(1);
+  parent.postMessage({ id: id, protocol: location.protocol }, "*");
+</script>