Bug 1298370 - Add SameSite attribute to Cookie Inspector r?pbro draft
authorMichael Ratcliffe <mratcliffe@mozilla.com>
Tue, 28 Nov 2017 14:29:09 +0000
changeset 704365 4ffb41fc814ab08d3baa127e16788a1126b8d380
parent 704194 5b33b070378ae0806bed0b5e5e34de429a29e7db
child 742083 05b372151d48b241000d28a279afcdf747dc8a27
push id91165
push userbmo:mratcliffe@mozilla.com
push dateTue, 28 Nov 2017 16:19:56 +0000
reviewerspbro
bugs1298370
milestone59.0a1
Bug 1298370 - Add SameSite attribute to Cookie Inspector r?pbro MozReview-Commit-ID: C0n35vEaAdJ
devtools/client/locales/en-US/storage.properties
devtools/client/storage/test/browser.ini
devtools/client/storage/test/browser_storage_cookies_samesite.js
devtools/client/storage/test/storage-cookies-samesite.html
devtools/server/actors/storage.js
--- a/devtools/client/locales/en-US/storage.properties
+++ b/devtools/client/locales/en-US/storage.properties
@@ -38,16 +38,17 @@ tree.labels.Cache=Cache Storage
 table.headers.cookies.uniqueKey=Unique key
 table.headers.cookies.name=Name
 table.headers.cookies.path=Path
 table.headers.cookies.host=Domain
 table.headers.cookies.expires=Expires on
 table.headers.cookies.value=Value
 table.headers.cookies.lastAccessed=Last accessed on
 table.headers.cookies.creationTime=Created on
+table.headers.cookies.sameSite=sameSite
 
 table.headers.localStorage.name=Key
 table.headers.localStorage.value=Value
 
 table.headers.sessionStorage.name=Key
 table.headers.sessionStorage.value=Value
 
 table.headers.Cache.url=URL
--- a/devtools/client/storage/test/browser.ini
+++ b/devtools/client/storage/test/browser.ini
@@ -1,15 +1,16 @@
 [DEFAULT]
 tags = devtools
 subsuite = devtools
 support-files =
   storage-cache-error.html
   storage-complex-values.html
   storage-cookies.html
+  storage-cookies-samesite.html
   storage-empty-objectstores.html
   storage-idb-delete-blocked.html
   storage-indexeddb-duplicate-names.html
   storage-listings.html
   storage-listings-usercontextid.html
   storage-listings-with-fragment.html
   storage-localstorage.html
   storage-overflow.html
@@ -31,16 +32,17 @@ tags = usercontextid
 [browser_storage_cache_delete.js]
 [browser_storage_cache_error.js]
 [browser_storage_cookies_add.js]
 [browser_storage_cookies_delete_all.js]
 [browser_storage_cookies_domain.js]
 [browser_storage_cookies_domain_port.js]
 [browser_storage_cookies_edit.js]
 [browser_storage_cookies_edit_keyboard.js]
+[browser_storage_cookies_samesite.js]
 [browser_storage_cookies_tab_navigation.js]
 [browser_storage_delete.js]
 [browser_storage_delete_all.js]
 [browser_storage_delete_tree.js]
 [browser_storage_delete_usercontextid.js]
 tags = usercontextid
 [browser_storage_dom_cache_disabled.js]
 [browser_storage_dynamic_updates_cookies.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/storage/test/browser_storage_cookies_samesite.js
@@ -0,0 +1,37 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* import-globals-from ../../framework/test/shared-head.js */
+
+"use strict";
+
+// Test that the samesite cookie attribute is displayed correctly.
+
+add_task(function* () {
+  yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-cookies-samesite.html");
+
+  let id1 = getCookieId("test1", "test1.example.org",
+                        "/browser/devtools/client/storage/test/");
+  let id2 = getCookieId("test2", "test1.example.org",
+                        "/browser/devtools/client/storage/test/");
+  let id3 = getCookieId("test3", "test1.example.org",
+                        "/browser/devtools/client/storage/test/");
+
+  yield checkState([
+    [
+      ["cookies", "http://test1.example.org"],
+      [ id1, id2, id3 ]
+    ]
+  ]);
+
+  let sameSite1 = getRowValues(id1).sameSite;
+  let sameSite2 = getRowValues(id2).sameSite;
+  let sameSite3 = getRowValues(id3).sameSite;
+
+  is(sameSite1, "Unset", `sameSite1 is "Unset"`);
+  is(sameSite2, "Lax", `sameSite2 is "Lax"`);
+  is(sameSite3, "Strict", `sameSite3 is "Strict"`);
+
+  yield finishTests();
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/storage/test/storage-cookies-samesite.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Storage inspector cookie samesite test</title>
+  </head>
+  <body>
+    <script type="application/javascript;version=1.7">
+    "use strict";
+    let expiresIn24Hours = new Date(Date.now() + 60 * 60 * 24 * 1000).toUTCString();
+
+    document.cookie = "test1=value1;expires=" + expiresIn24Hours + ";";
+    document.cookie = "test2=value2;expires=" + expiresIn24Hours + ";SameSite=lax";
+    document.cookie = "test3=value3;expires=" + expiresIn24Hours + ";SameSite=strict";
+    </script>
+  </body>
+</html>
--- a/devtools/server/actors/storage.js
+++ b/devtools/server/actors/storage.js
@@ -15,16 +15,24 @@ const {isWindowIncluded} = require("devt
 const specs = require("devtools/shared/specs/storage");
 const { Task } = require("devtools/shared/task");
 
 const DEFAULT_VALUE = "value";
 
 loader.lazyRequireGetter(this, "naturalSortCaseInsensitive",
   "devtools/client/shared/natural-sort", true);
 
+// "Lax", "Strict" and "Unset" are special values of the sameSite property
+// that should not be translated.
+const COOKIE_SAMESITE = {
+  LAX: "Lax",
+  STRICT: "Strict",
+  UNSET: "Unset"
+};
+
 // GUID to be used as a separator in compound keys. This must match the same
 // constant in devtools/client/storage/ui.js,
 // devtools/client/storage/test/head.js and
 // devtools/server/tests/browser/head.js
 const SEPARATOR_GUID = "{9d414cc5-8319-0a04-0586-c0a6ae01670a}";
 
 loader.lazyImporter(this, "OS", "resource://gre/modules/osfile.jsm");
 loader.lazyImporter(this, "Sqlite", "resource://gre/modules/Sqlite.jsm");
@@ -535,20 +543,32 @@ StorageActors.createActor({
       // because creationTime is in micro seconds
       creationTime: cookie.creationTime / 1000,
 
       // - do -
       lastAccessed: cookie.lastAccessed / 1000,
       value: new LongStringActor(this.conn, cookie.value || ""),
       isDomain: cookie.isDomain,
       isSecure: cookie.isSecure,
-      isHttpOnly: cookie.isHttpOnly
+      isHttpOnly: cookie.isHttpOnly,
+      sameSite: this.getSameSiteStringFromCookie(cookie)
     };
   },
 
+  getSameSiteStringFromCookie(cookie) {
+    switch (cookie.sameSite) {
+      case cookie.SAMESITE_LAX:
+        return COOKIE_SAMESITE.LAX;
+      case cookie.SAMESITE_STRICT:
+        return COOKIE_SAMESITE.STRICT;
+    }
+    // cookie.SAMESITE_UNSET
+    return COOKIE_SAMESITE.UNSET;
+  },
+
   populateStoresForHost(host) {
     this.hostVsStores.set(host, new Map());
     let doc = this.storageActor.document;
 
     let cookies = this.getCookiesFromHost(host, doc.nodePrincipal
                                                    .originAttributes);
 
     for (let cookie of cookies) {
@@ -648,17 +668,18 @@ StorageActors.createActor({
       { name: "host", editable: true, hidden: false },
       { name: "path", editable: true, hidden: false },
       { name: "expires", editable: true, hidden: false },
       { name: "lastAccessed", editable: false, hidden: false },
       { name: "creationTime", editable: false, hidden: true },
       { name: "value", editable: true, hidden: false },
       { name: "isDomain", editable: false, hidden: true },
       { name: "isSecure", editable: true, hidden: true },
-      { name: "isHttpOnly", editable: true, hidden: false }
+      { name: "isHttpOnly", editable: true, hidden: false },
+      { name: "sameSite", editable: false, hidden: false }
     ];
   }),
 
   /**
    * Pass the editItem command from the content to the chrome process.
    *
    * @param {Object} data
    *        See editCookie() for format details.