# HG changeset patch # User Vincent Lequertier # Date 1525537460 -7200 # Node ID 782b1ae19860ca6c80dad92aedfb6e06689fcef0 # Parent ebb348330a3d3ad9c2475f8b6adb99a87ff2db39 Bug 1452715 - Add support for same-site cookie attribute to "Cookies" netmonitor side-panel; r=Honza MozReview-Commit-ID: ESP8L9vqNjU diff --git a/devtools/client/netmonitor/test/browser.ini b/devtools/client/netmonitor/test/browser.ini --- a/devtools/client/netmonitor/test/browser.ini +++ b/devtools/client/netmonitor/test/browser.ini @@ -39,16 +39,17 @@ support-files = html_api-calls-test-page.html html_copy-as-curl.html html_curl-utils.html sjs_content-type-test-server.sjs sjs_cors-test-server.sjs sjs_https-redirect-test-server.sjs sjs_hsts-test-server.sjs sjs_json-test-server.sjs + sjs_set-cookie-same-site.sjs sjs_simple-test-server.sjs sjs_simple-unsorted-cookies-test-server.sjs sjs_sorting-test-server.sjs sjs_status-codes-test-server.sjs sjs_truncate-test-server.sjs test-image.png service-workers/status-codes.html service-workers/status-codes-service-worker.js @@ -162,16 +163,17 @@ skip-if = os == 'win' # bug 1391264 [browser_net_security-icon-click.js] [browser_net_security-redirect.js] [browser_net_security-state.js] [browser_net_security-tab-deselect.js] [browser_net_security-tab-visibility.js] [browser_net_security-warnings.js] [browser_net_send-beacon.js] [browser_net_send-beacon-other-tab.js] +[browser_net_set-cookie-same-site.js] [browser_net_simple-request-data.js] [browser_net_simple-request-details.js] skip-if = true # Bug 1258809 [browser_net_simple-request.js] [browser_net_sort-01.js] [browser_net_sort-02.js] [browser_net_statistics-01.js] skip-if = true # Bug 1373558 diff --git a/devtools/client/netmonitor/test/browser_net_set-cookie-same-site.js b/devtools/client/netmonitor/test/browser_net_set-cookie-same-site.js new file mode 100644 --- /dev/null +++ b/devtools/client/netmonitor/test/browser_net_set-cookie-same-site.js @@ -0,0 +1,74 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Test if the 'Same site' cookie attribute is correctly set in the cookie panel + */ +add_task(async function() { + let { tab, monitor } = await initNetMonitor(SET_COOKIE_SAME_SITE_SJS); + info("Starting test... "); + + let { document, store, windowRequire } = monitor.panelWin; + let Actions = windowRequire("devtools/client/netmonitor/src/actions/index"); + + store.dispatch(Actions.batchEnable(false)); + tab.linkedBrowser.reload(); + + let wait = waitForNetworkEvents(monitor, 1); + await wait; + + wait = waitForDOM(document, ".headers-overview"); + EventUtils.sendMouseEvent({ type: "mousedown" }, + document.querySelectorAll(".request-list-item")[0]); + await wait; + + EventUtils.sendMouseEvent({ type: "click" }, + document.querySelector("#cookies-tab")); + + info("Checking the SameSite property"); + const expectedValues = [ + { + key: "Response cookies", + value: "" + }, + { + key: "foo", + value: "" + }, + { + key: "samesite", + value: "Lax" + }, + { + key: "value", + value: "bar" + }, + { + key: "Request cookies", + value: "" + }, + { + key: "foo", + value: "bar" + }, + ]; + let labelCells = document.querySelectorAll(".treeLabelCell"); + let valueCells = document.querySelectorAll(".treeValueCell"); + is(valueCells.length, labelCells.length, "Number of labels " + + labelCells.length + " different from number of values " + valueCells.length); + + // Go through the cookie properties and check if each one has the expected + // label and value + for (let index = 0; index < labelCells.length; ++index) { + is(labelCells[index].innerText, expectedValues[index].key, + "Actual label " + labelCells[index].innerText + + " not equal to expected label " + expectedValues[index].key); + is(valueCells[index].innerText, expectedValues[index].value, + "Actual value " + valueCells[index].innerText + + " not equal to expected value " + expectedValues[index].value); + } + + await teardown(monitor); +}); diff --git a/devtools/client/netmonitor/test/head.js b/devtools/client/netmonitor/test/head.js --- a/devtools/client/netmonitor/test/head.js +++ b/devtools/client/netmonitor/test/head.js @@ -67,16 +67,17 @@ const SIMPLE_SJS = EXAMPLE_URL + "sjs_si const SIMPLE_UNSORTED_COOKIES_SJS = EXAMPLE_URL + "sjs_simple-unsorted-cookies-test-server.sjs"; const CONTENT_TYPE_SJS = EXAMPLE_URL + "sjs_content-type-test-server.sjs"; const HTTPS_CONTENT_TYPE_SJS = HTTPS_EXAMPLE_URL + "sjs_content-type-test-server.sjs"; const STATUS_CODES_SJS = EXAMPLE_URL + "sjs_status-codes-test-server.sjs"; const SORTING_SJS = EXAMPLE_URL + "sjs_sorting-test-server.sjs"; const HTTPS_REDIRECT_SJS = EXAMPLE_URL + "sjs_https-redirect-test-server.sjs"; const CORS_SJS_PATH = "/browser/devtools/client/netmonitor/test/sjs_cors-test-server.sjs"; const HSTS_SJS = EXAMPLE_URL + "sjs_hsts-test-server.sjs"; +const SET_COOKIE_SAME_SITE_SJS = EXAMPLE_URL + "sjs_set-cookie-same-site.sjs"; const HSTS_BASE_URL = EXAMPLE_URL; const HSTS_PAGE_URL = CUSTOM_GET_URL; const TEST_IMAGE = EXAMPLE_URL + "test-image.png"; const TEST_IMAGE_DATA_URI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="; /* eslint-enable no-unused-vars, max-len */ diff --git a/devtools/client/netmonitor/test/sjs_set-cookie-same-site.sjs b/devtools/client/netmonitor/test/sjs_set-cookie-same-site.sjs new file mode 100644 --- /dev/null +++ b/devtools/client/netmonitor/test/sjs_set-cookie-same-site.sjs @@ -0,0 +1,10 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +function handleRequest(request, response) { + response.setStatusLine(request.httpVersion, 200, "Och Aye"); + + response.setHeader("Set-Cookie", "foo=bar; SameSite=Lax"); + + response.write("Hello world!"); +} diff --git a/devtools/shared/webconsole/network-helper.js b/devtools/shared/webconsole/network-helper.js --- a/devtools/shared/webconsole/network-helper.js +++ b/devtools/shared/webconsole/network-helper.js @@ -64,16 +64,24 @@ loader.lazyImporter(this, "NetUtil", "re const DevToolsUtils = require("devtools/shared/DevToolsUtils"); const Services = require("Services"); const { LocalizationHelper } = require("devtools/shared/l10n"); const L10N = new LocalizationHelper("devtools/client/locales/netmonitor.properties"); // The cache used in the `nsIURL` function. const gNSURLStore = new Map(); +// "Lax", "Strict" and "Unset" are special values of the SameSite cookie +// attribute that should not be translated. +const COOKIE_SAMESITE = { + LAX: "Lax", + STRICT: "Strict", + UNSET: "Unset" +}; + /** * Helper object for networking stuff. * * Most of the following functions have been taken from the Firebug source. They * have been modified to match the Firefox coding rules. */ var NetworkHelper = { /** @@ -348,19 +356,30 @@ var NetworkHelper = { /** * Parse a raw Set-Cookie header value. * * @param string header * The raw Set-Cookie header value. * @return array * Array holding an object for each cookie. Each object holds the * following properties: name, value, secure (boolean), httpOnly - * (boolean), path, domain and expires (ISO date string). + * (boolean), path, domain, samesite and expires (ISO date string). */ parseSetCookieHeader: function(header) { + function parseSameSiteAttribute(attribute) { + switch (attribute) { + case COOKIE_SAMESITE.LAX: + return COOKIE_SAMESITE.LAX; + case COOKIE_SAMESITE.STRICT: + return COOKIE_SAMESITE.STRICT; + default: + return COOKIE_SAMESITE.UNSET; + } + } + let rawCookies = header.split(/\r\n|\n|\r/); let cookies = []; rawCookies.forEach(function(cookie) { let equal = cookie.indexOf("="); let name = unescape(cookie.substr(0, equal).trim()); let parts = cookie.substr(equal + 1).split(";"); let value = unescape(parts.shift().trim()); @@ -373,16 +392,18 @@ var NetworkHelper = { cookie.secure = true; } else if (part.toLowerCase() == "httponly") { cookie.httpOnly = true; } else if (part.indexOf("=") > -1) { let pair = part.split("="); pair[0] = pair[0].toLowerCase(); if (pair[0] == "path" || pair[0] == "domain") { cookie[pair[0]] = pair[1]; + } else if (pair[0] == "samesite") { + cookie[pair[0]] = parseSameSiteAttribute(pair[1]); } else if (pair[0] == "expires") { try { pair[1] = pair[1].replace(/-/g, " "); cookie.expires = new Date(pair[1]).toISOString(); } catch (ex) { // Ignore. } }