Bug 1162411 - Fix Request CORS bug. r=bz
authorNikhil Marathe <nsm.nikhil@gmail.com>
Thu, 07 May 2015 15:39:13 -0700
changeset 274441 4d40d05a58df64cc0b46169981746e40ce15c4a5
parent 274440 790507f83bf3406e7a8fb6f90b6a1a5583f4f98e
child 274442 352218aee2620ba70136ae1549c6aaec39b1b949
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1162411
milestone40.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 1162411 - Fix Request CORS bug. r=bz
dom/cache/test/mochitest/test_cache_match_vary.js
dom/fetch/Request.cpp
dom/tests/mochitest/fetch/test_request.js
--- a/dom/cache/test/mochitest/test_cache_match_vary.js
+++ b/dom/cache/test/mochitest/test_cache_match_vary.js
@@ -30,17 +30,17 @@ function setupTest(headers) {
             cache: test.cache};
   });
 }
 function setupTestMultipleEntries(headers) {
   ok(Array.isArray(headers), "headers should be an array");
   return new Promise(function(resolve, reject) {
     var response, responseText, cache;
     Promise.all(headers.map(function(h) {
-      return fetch(new Request(requestURL, {headers: h}));
+      return fetch(requestURL, {headers: h});
     })).then(function(r) {
         response = r;
         return Promise.all(response.map(function(r) {
           return r.text();
         }));
       }).then(function(text) {
         responseText = text;
         return caches.open(name);
@@ -54,57 +54,57 @@ function setupTestMultipleEntries(header
       }).catch(function(err) {
         reject(err);
       });
   });
 }
 
 function testBasics() {
   var test;
-  return setupTest({"WhatToVary": "Cookie"})
+  return setupTest({"WhatToVary": "Custom"})
     .then(function(t) {
       test = t;
-      // Ensure that searching without specifying a Cookie header succeeds.
+      // Ensure that searching without specifying a Custom header succeeds.
       return test.cache.match(requestURL);
     }).then(function(r) {
       return checkResponse(r, test.response, test.responseText);
     }).then(function() {
-      // Ensure that searching with a non-matching value for the Cookie header fails.
-      return test.cache.match(new Request(requestURL, {headers: {"Cookie": "foo=bar"}}));
+      // Ensure that searching with a non-matching value for the Custom header fails.
+      return test.cache.match(new Request(requestURL, {headers: {"Custom": "foo=bar"}}));
     }).then(function(r) {
       is(typeof r, "undefined", "Searching for a request with an unknown Vary header should not succeed");
-      // Ensure that searching with a non-matching value for the Cookie header but with ignoreVary set succeeds.
-      return test.cache.match(new Request(requestURL, {headers: {"Cookie": "foo=bar"}}),
+      // Ensure that searching with a non-matching value for the Custom header but with ignoreVary set succeeds.
+      return test.cache.match(new Request(requestURL, {headers: {"Custom": "foo=bar"}}),
                               {ignoreVary: true});
     }).then(function(r) {
       return checkResponse(r, test.response, test.responseText);
     });
 }
 
 function testBasicKeys() {
   function checkRequest(reqs) {
     is(reqs.length, 1, "One request expected");
     ok(reqs[0].url.indexOf(requestURL) >= 0, "The correct request expected");
-    ok(reqs[0].headers.get("WhatToVary"), "Cookie", "The correct request headers expected");
+    ok(reqs[0].headers.get("WhatToVary"), "Custom", "The correct request headers expected");
   }
   var test;
-  return setupTest({"WhatToVary": "Cookie"})
+  return setupTest({"WhatToVary": "Custom"})
     .then(function(t) {
       test = t;
-      // Ensure that searching without specifying a Cookie header succeeds.
+      // Ensure that searching without specifying a Custom header succeeds.
       return test.cache.keys(requestURL);
     }).then(function(r) {
       return checkRequest(r);
     }).then(function() {
-      // Ensure that searching with a non-matching value for the Cookie header fails.
-      return test.cache.keys(new Request(requestURL, {headers: {"Cookie": "foo=bar"}}));
+      // Ensure that searching with a non-matching value for the Custom header fails.
+      return test.cache.keys(new Request(requestURL, {headers: {"Custom": "foo=bar"}}));
     }).then(function(r) {
       is(r.length, 0, "Searching for a request with an unknown Vary header should not succeed");
-      // Ensure that searching with a non-matching value for the Cookie header but with ignoreVary set succeeds.
-      return test.cache.keys(new Request(requestURL, {headers: {"Cookie": "foo=bar"}}),
+      // Ensure that searching with a non-matching value for the Custom header but with ignoreVary set succeeds.
+      return test.cache.keys(new Request(requestURL, {headers: {"Custom": "foo=bar"}}),
                              {ignoreVary: true});
     }).then(function(r) {
       return checkRequest(r);
     });
 }
 
 function testStar() {
   function ensurePromiseRejected(promise) {
@@ -159,95 +159,95 @@ function testStar() {
             })),
       ]).then(reject, resolve);
     });
   });
 }
 
 function testMatch() {
   var test;
-  return setupTest({"WhatToVary": "Cookie", "Cookie": "foo=bar"})
+  return setupTest({"WhatToVary": "Custom", "Custom": "foo=bar"})
     .then(function(t) {
       test = t;
-      // Ensure that searching with a different Cookie header fails.
-      return test.cache.match(new Request(requestURL, {headers: {"Cookie": "bar=baz"}}));
+      // Ensure that searching with a different Custom header fails.
+      return test.cache.match(new Request(requestURL, {headers: {"Custom": "bar=baz"}}));
     }).then(function(r) {
-      is(typeof r, "undefined", "Searching for a request with a non-matching Cookie header should not succeed");
-      // Ensure that searching with the same Cookie header succeeds.
-      return test.cache.match(new Request(requestURL, {headers: {"Cookie": "foo=bar"}}));
+      is(typeof r, "undefined", "Searching for a request with a non-matching Custom header should not succeed");
+      // Ensure that searching with the same Custom header succeeds.
+      return test.cache.match(new Request(requestURL, {headers: {"Custom": "foo=bar"}}));
     }).then(function(r) {
       return checkResponse(r, test.response, test.responseText);
     });
 }
 
 function testInvalidHeaderName() {
   var test;
-  return setupTest({"WhatToVary": "Foo/Bar, User-Agent"})
+  return setupTest({"WhatToVary": "Foo/Bar, Custom-User-Agent"})
     .then(function(t) {
       test = t;
       // Ensure that searching with a different User-Agent header fails.
-      return test.cache.match(new Request(requestURL, {headers: {"User-Agent": "MyUA"}}));
+      return test.cache.match(new Request(requestURL, {headers: {"Custom-User-Agent": "MyUA"}}));
     }).then(function(r) {
-      is(typeof r, "undefined", "Searching for a request with a non-matching User-Agent header should not succeed");
-      // Ensure that searching with a different User-Agent header but with ignoreVary succeeds.
-      return test.cache.match(new Request(requestURL, {headers: {"User-Agent": "MyUA"}}),
+      is(typeof r, "undefined", "Searching for a request with a non-matching Custom-User-Agent header should not succeed");
+      // Ensure that searching with a different Custom-User-Agent header but with ignoreVary succeeds.
+      return test.cache.match(new Request(requestURL, {headers: {"Custom-User-Agent": "MyUA"}}),
                               {ignoreVary: true});
     }).then(function(r) {
       return checkResponse(r, test.response, test.responseText);
     }).then(function() {
       // Ensure that we do not mistakenly recognize the tokens in the invalid header name.
       return test.cache.match(new Request(requestURL, {headers: {"Foo": "foobar"}}));
     }).then(function(r) {
       return checkResponse(r, test.response, test.responseText);
     });
 }
 
 function testMultipleHeaders() {
   var test;
-  return setupTest({"WhatToVary": "Referer,\tAccept-Encoding"})
+  return setupTest({"WhatToVary": "Custom-Referer,\tCustom-Accept-Encoding"})
     .then(function(t) {
       test = t;
       // Ensure that searching with a different Referer header fails.
-      return test.cache.match(new Request(requestURL, {headers: {"Referer": "https://somesite.com/"}}));
+      return test.cache.match(new Request(requestURL, {headers: {"Custom-Referer": "https://somesite.com/"}}));
     }).then(function(r) {
-      is(typeof r, "undefined", "Searching for a request with a non-matching Referer header should not succeed");
-      // Ensure that searching with a different Referer header but with ignoreVary succeeds.
-      return test.cache.match(new Request(requestURL, {headers: {"Referer": "https://somesite.com/"}}),
+      is(typeof r, "undefined", "Searching for a request with a non-matching Custom-Referer header should not succeed");
+      // Ensure that searching with a different Custom-Referer header but with ignoreVary succeeds.
+      return test.cache.match(new Request(requestURL, {headers: {"Custom-Referer": "https://somesite.com/"}}),
                               {ignoreVary: true});
     }).then(function(r) {
       return checkResponse(r, test.response, test.responseText);
     }).then(function() {
-      // Ensure that searching with a different Accept-Encoding header fails.
-      return test.cache.match(new Request(requestURL, {headers: {"Accept-Encoding": "myencoding"}}));
+      // Ensure that searching with a different Custom-Accept-Encoding header fails.
+      return test.cache.match(new Request(requestURL, {headers: {"Custom-Accept-Encoding": "myencoding"}}));
     }).then(function(r) {
-      is(typeof r, "undefined", "Searching for a request with a non-matching Accept-Encoding header should not succeed");
-      // Ensure that searching with a different Accept-Encoding header but with ignoreVary succeeds.
-      return test.cache.match(new Request(requestURL, {headers: {"Accept-Encoding": "myencoding"}}),
+      is(typeof r, "undefined", "Searching for a request with a non-matching Custom-Accept-Encoding header should not succeed");
+      // Ensure that searching with a different Custom-Accept-Encoding header but with ignoreVary succeeds.
+      return test.cache.match(new Request(requestURL, {headers: {"Custom-Accept-Encoding": "myencoding"}}),
                               {ignoreVary: true});
     }).then(function(r) {
       return checkResponse(r, test.response, test.responseText);
     }).then(function() {
-      // Ensure that searching with an empty Referer header succeeds.
-      return test.cache.match(new Request(requestURL, {headers: {"Referer": ""}}));
+      // Ensure that searching with an empty Custom-Referer header succeeds.
+      return test.cache.match(new Request(requestURL, {headers: {"Custom-Referer": ""}}));
     }).then(function(r) {
       return checkResponse(r, test.response, test.responseText);
     }).then(function() {
-      // Ensure that searching with an empty Accept-Encoding header succeeds.
-      return test.cache.match(new Request(requestURL, {headers: {"Accept-Encoding": ""}}));
+      // Ensure that searching with an empty Custom-Accept-Encoding header succeeds.
+      return test.cache.match(new Request(requestURL, {headers: {"Custom-Accept-Encoding": ""}}));
     }).then(function(r) {
       return checkResponse(r, test.response, test.responseText);
     }).then(function() {
-      // Ensure that searching with an empty Referer header but with a different Accept-Encoding header fails.
-      return test.cache.match(new Request(requestURL, {headers: {"Referer": "",
-                                                                 "Accept-Encoding": "myencoding"}}));
+      // Ensure that searching with an empty Custom-Referer header but with a different Custom-Accept-Encoding header fails.
+      return test.cache.match(new Request(requestURL, {headers: {"Custom-Referer": "",
+                                                                 "Custom-Accept-Encoding": "myencoding"}}));
     }).then(function(r) {
-      is(typeof r, "undefined", "Searching for a request with a non-matching Accept-Encoding header should not succeed");
-      // Ensure that searching with an empty Referer header but with a different Accept-Encoding header and ignoreVary succeeds.
-      return test.cache.match(new Request(requestURL, {headers: {"Referer": "",
-                                                                 "Accept-Encoding": "myencoding"}}),
+      is(typeof r, "undefined", "Searching for a request with a non-matching Custom-Accept-Encoding header should not succeed");
+      // Ensure that searching with an empty Custom-Referer header but with a different Custom-Accept-Encoding header and ignoreVary succeeds.
+      return test.cache.match(new Request(requestURL, {headers: {"Custom-Referer": "",
+                                                                 "Custom-Accept-Encoding": "myencoding"}}),
                               {ignoreVary: true});
     }).then(function(r) {
       return checkResponse(r, test.response, test.responseText);
     });
 }
 
 function testMultipleCacheEntries() {
   var test;
--- a/dom/fetch/Request.cpp
+++ b/dom/fetch/Request.cpp
@@ -258,16 +258,20 @@ Request::Constructor(const GlobalObject&
     }
     request->ClearCreatedByFetchEvent();
     headers = h->GetInternalHeaders();
   } else {
     headers = new InternalHeaders(*requestHeaders);
   }
 
   requestHeaders->Clear();
+  // From "Let r be a new Request object associated with request and a new
+  // Headers object whose guard is "request"."
+  requestHeaders->SetGuard(HeadersGuardEnum::Request, aRv);
+  MOZ_ASSERT(!aRv.Failed());
 
   if (request->Mode() == RequestMode::No_cors) {
     if (!request->HasSimpleMethod()) {
       nsAutoCString method;
       request->GetMethod(method);
       NS_ConvertUTF8toUTF16 label(method);
       aRv.ThrowTypeError(MSG_INVALID_REQUEST_METHOD, &label);
       return nullptr;
--- a/dom/tests/mochitest/fetch/test_request.js
+++ b/dom/tests/mochitest/fetch/test_request.js
@@ -18,29 +18,29 @@ function testDefaultCtor() {
   is(req.mode, "cors", "Request mode string input is cors");
   is(req.credentials, "omit", "Default Request credentials is omit");
   is(req.cache, "default", "Default Request cache is default");
 }
 
 function testClone() {
   var orig = new Request("./cloned_request.txt", {
               method: 'POST',
-              headers: { "Content-Length": 5 },
+              headers: { "Sample-Header": "5" },
               body: "Sample body",
               mode: "same-origin",
               credentials: "same-origin",
               cache: "no-store",
             });
   var clone = orig.clone();
   ok(clone.method === "POST", "Request method is POST");
   ok(clone.headers instanceof Headers, "Request should have non-null Headers object");
 
-  is(clone.headers.get('content-length'), "5", "Response content-length should be 5.");
-  orig.headers.set('content-length', 6);
-  is(clone.headers.get('content-length'), "5", "Request content-length should be 5.");
+  is(clone.headers.get('sample-header'), "5", "Request sample-header should be 5.");
+  orig.headers.set('sample-header', 6);
+  is(clone.headers.get('sample-header'), "5", "Cloned Request sample-header should continue to be 5.");
 
   ok(clone.url === (new URL("./cloned_request.txt", self.location.href)).href,
        "URL should be resolved with entry settings object's API base URL");
   ok(clone.referrer === "about:client", "Default referrer is `client` which serializes to about:client.");
   ok(clone.mode === "same-origin", "Request mode is same-origin");
   ok(clone.credentials === "same-origin", "Default credentials is same-origin");
   ok(clone.cache === "no-store", "Default cache is no-store");
 
@@ -119,16 +119,30 @@ function testBug1109574() {
   var r1 = new Request("");
   is(r1.bodyUsed, false, "Initial value of bodyUsed should be false");
   var r2 = new Request(r1);
   is(r1.bodyUsed, false, "Request with null body should not have bodyUsed set");
   // This should succeed.
   var r3 = new Request(r1);
 }
 
+function testHeaderGuard() {
+  var headers = {
+    "Cookie": "Custom cookie",
+    "Non-Simple-Header": "value",
+  };
+  var r1 = new Request("", { headers: headers });
+  ok(!r1.headers.has("Cookie"), "Default Request header should have guard request and prevent setting forbidden header.");
+  ok(r1.headers.has("Non-Simple-Header"), "Default Request header should have guard request and allow setting non-simple header.");
+
+  var r2 = new Request("", { mode: "no-cors", headers: headers });
+  ok(!r2.headers.has("Cookie"), "no-cors Request header should have guard request-no-cors and prevent setting non-simple header.");
+  ok(!r2.headers.has("Non-Simple-Header"), "no-cors Request header should have guard request-no-cors and prevent setting non-simple header.");
+}
+
 function testMethod() {
   // These get normalized.
   var allowed = ["delete", "get", "head", "options", "post", "put" ];
   for (var i = 0; i < allowed.length; ++i) {
     try {
       var r = new Request("", { method: allowed[i] });
       ok(true, "Method " + allowed[i] + " should be allowed");
       is(r.method, allowed[i].toUpperCase(),
@@ -429,16 +443,17 @@ function testModeCorsPreflightEnumValue(
 }
 
 function runTest() {
   testDefaultCtor();
   testSimpleUrlParse();
   testUrlFragment();
   testMethod();
   testBug1109574();
+  testHeaderGuard();
   testModeCorsPreflightEnumValue();
 
   return Promise.resolve()
     .then(testBodyCreation)
     .then(testBodyUsed)
     .then(testBodyExtraction)
     .then(testFormDataBodyCreation)
     .then(testFormDataBodyExtraction)