Bug 1323036 - Preserve case of header names
MozReview-Commit-ID: 2jDHOr2GI6T
--- a/toolkit/components/extensions/test/mochitest/test_ext_webrequest_basic.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_webrequest_basic.html
@@ -317,15 +317,63 @@ add_task(function* test_webRequest_frame
addFrame("redirection.sjs");
addFrame("https://invalid.localhost/badrobot");
yield extension.awaitMessage("done");
});
add_task(function* teardown() {
yield extension.unload();
});
+
+add_task(async function test_case_preserving() {
+ const manifest = {
+ permissions: [
+ "webRequest",
+ "webRequestBlocking",
+ "http://mochi.test/",
+ ],
+ };
+
+ async function background() {
+ // This is testing if header names preserve case,
+ // so the case-sensitive comparison is on purpose.
+ function ua({url, requestHeaders}) {
+ if (url.endsWith("?blind-add")) {
+ requestHeaders.push({name: "user-agent", value: "Blind/Add"});
+ return {requestHeaders};
+ }
+ for (const header of requestHeaders) {
+ if (header.name === "User-Agent") {
+ header.value = "Case/Sensitive";
+ }
+ }
+ return {requestHeaders};
+ }
+
+ await browser.webRequest.onBeforeSendHeaders.addListener(ua, {urls: ["<all_urls>"]}, ["blocking", "requestHeaders"]);
+ browser.test.sendMessage("ready");
+ }
+
+ const extension = ExtensionTestUtils.loadExtension({manifest, background});
+
+ await extension.startup();
+ await extension.awaitMessage("ready");
+
+ const response1 = await fetch(SimpleTest.getTestFileURL("return_headers.sjs"));
+ const headers1 = JSON.parse(await response1.text());
+
+ is(headers1["user-agent"], "Case/Sensitive", "User-Agent header matched and changed.");
+
+ const response2 = await fetch(SimpleTest.getTestFileURL("return_headers.sjs?blind-add"));
+ const headers2 = JSON.parse(await response2.text());
+
+ is(headers2["user-agent"], "Blind/Add", "User-Agent header blindly added.");
+
+ await extension.unload();
+});
+
</script>
</head>
<body>
<div id="test">Sample text</div>
</body>
</html>
--- a/toolkit/modules/addons/WebRequest.jsm
+++ b/toolkit/modules/addons/WebRequest.jsm
@@ -119,23 +119,23 @@ function isThenable(value) {
}
class HeaderChanger {
constructor(channel) {
this.channel = channel;
this.originalHeaders = new Map();
this.visitHeaders((name, value) => {
- this.originalHeaders.set(name.toLowerCase(), value);
+ this.originalHeaders.set(name.toLowerCase(), {name, value});
});
}
toArray() {
return Array.from(this.originalHeaders,
- ([name, value]) => ({name, value}));
+ ([key, {name, value}]) => ({name, value}));
}
validateHeaders(headers) {
// We should probably use schema validation for this.
if (!Array.isArray(headers)) {
return false;
}
@@ -171,17 +171,18 @@ class HeaderChanger {
}
}
// Set new or changed headers.
for (let {name, value, binaryValue} of headers) {
if (binaryValue) {
value = String.fromCharCode(...binaryValue);
}
- if (value !== this.originalHeaders.get(name.toLowerCase())) {
+ let original = this.originalHeaders.get(name.toLowerCase());
+ if (!original || value !== original.value) {
this.setHeader(name, value);
}
}
}
}
class RequestHeaderChanger extends HeaderChanger {
setHeader(name, value) {