Bug 1622306 - Group cookie console info/warning logs, r=nchevobbe
authorAndrea Marchesini <amarchesini@mozilla.com>
Tue, 24 Mar 2020 09:41:07 +0000
changeset 520196 385bf7e04abb926a6d80c378f6ca00c8069604b4
parent 520195 8995d7dbb8f0f8cade58613eccc05b29e0f55da7
child 520197 d972e8f4606f6999f462de6793c621638be7b87f
push id37245
push useropoprus@mozilla.com
push dateTue, 24 Mar 2020 21:46:41 +0000
treeherdermozilla-central@dbabf2e388fa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnchevobbe
bugs1622306
milestone76.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 1622306 - Group cookie console info/warning logs, r=nchevobbe Differential Revision: https://phabricator.services.mozilla.com/D66890
devtools/client/locales/en-US/webconsole.properties
devtools/client/webconsole/constants.js
devtools/client/webconsole/test/node/fixtures/L10n.js
devtools/client/webconsole/utils/messages.js
netwerk/cookie/nsCookieService.cpp
netwerk/cookie/nsCookieService.h
--- a/devtools/client/locales/en-US/webconsole.properties
+++ b/devtools/client/locales/en-US/webconsole.properties
@@ -521,8 +521,13 @@ webconsole.input.openJavaScriptFileFilte
 # LOCALIZATION NOTE (webconsole.input.selector.top): This is the term used
 # to describe the primary thread of execution in the page
 webconsole.input.selector.top=Top
 
 # LOCALIZATION NOTE (webconsole.input.selector.tooltip): This is the tooltip
 # shown when users select a thread that they want to evaluate an
 # expression for.
 webconsole.input.selector.tooltip=Select evaluation context
+
+# LOCALIZATION NOTE (webconsole.group.cookieSameSiteLaxByDefaultEnabled): do not translate 'sameSite'.
+webconsole.group.cookieSameSiteLaxByDefaultEnabled=Some cookies are misusing the “sameSite“ attribute, so it won’t work as expected
+# LOCALIZATION NOTE (webconsole.group.cookieSameSiteLaxByDefaultDisabled): do not translate 'sameSite'.
+webconsole.group.cookieSameSiteLaxByDefaultDisabled=Some cookies are misusing the recommended “sameSite“ attribute
--- a/devtools/client/webconsole/constants.js
+++ b/devtools/client/webconsole/constants.js
@@ -149,16 +149,17 @@ const chromeRDPEnums = {
     TABLE: "table",
     TRACE: "trace",
     CLEAR: "clear",
     START_GROUP: "startGroup",
     START_GROUP_COLLAPSED: "startGroupCollapsed",
     END_GROUP: "endGroup",
     CONTENT_BLOCKING_GROUP: "contentBlockingWarningGroup",
     TRACKING_PROTECTION_GROUP: "trackingProtectionWarningGroup",
+    COOKIE_SAMESITE_GROUP: "cookieSameSiteGroup",
     CORS_GROUP: "CORSWarningGroup",
     CSP_GROUP: "CSPWarningGroup",
     ASSERT: "assert",
     DEBUG: "debug",
     PROFILE: "profile",
     PROFILE_END: "profileEnd",
     // Undocumented in Chrome RDP, but is used for evaluation results.
     RESULT: "result",
--- a/devtools/client/webconsole/test/node/fixtures/L10n.js
+++ b/devtools/client/webconsole/test/node/fixtures/L10n.js
@@ -20,16 +20,20 @@ const strings = {
   "webconsole.xhrFilterButton.label": "XHR",
   "webconsole.requestsFilterButton.label": "Requests",
   "messageRepeats.tooltip2": "#1 repeat;#1 repeats",
   "webconsole.filteredMessagesByText.label": "#1 hidden;#1 hidden",
   "webconsole.filteredMessagesByText.tooltip":
     "#1 item hidden by text filter;#1 items hidden by text filter",
   cdFunctionInvalidArgument:
     "Cannot cd() to the given window. Invalid argument.",
+  "webconsole.group.cookieSameSiteLaxByDefaultEnabled":
+    "Some cookies are misusing the sameSite attribute, so it won't work as expected",
+  "webconsole.group.cookieSameSiteLaxByDefaultDisabled":
+    "Some cookies are misusing the recommended sameSite attribute",
 };
 
 // @TODO Load the actual strings from webconsole.properties instead.
 class L10n {
   getStr(str) {
     return strings[str] || str;
   }
 
--- a/devtools/client/webconsole/utils/messages.js
+++ b/devtools/client/webconsole/utils/messages.js
@@ -1,14 +1,15 @@
 /* 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/. */
 
 "use strict";
 
+const Services = require("Services");
 const l10n = require("devtools/client/webconsole/utils/l10n");
 const {
   getUrlDetails,
 } = require("devtools/client/netmonitor/src/utils/request-utils");
 
 // URL Regex, common idioms:
 //
 // Lead-in (URL):
@@ -559,16 +560,23 @@ function createWarningGroupMessage(id, t
 function getWarningGroupLabel(firstMessage) {
   if (
     isContentBlockingMessage(firstMessage) ||
     isTrackingProtectionMessage(firstMessage)
   ) {
     return replaceURL(firstMessage.messageText, "<URL>");
   }
 
+  if (isCookieSameSiteMessage(firstMessage)) {
+    if (Services.prefs.getBoolPref("network.cookie.sameSite.laxByDefault")) {
+      return l10n.getStr("webconsole.group.cookieSameSiteLaxByDefaultEnabled");
+    }
+    return l10n.getStr("webconsole.group.cookieSameSiteLaxByDefaultDisabled");
+  }
+
   return "";
 }
 
 /**
  * Replace any URL in the provided text by the provided replacement text, or an empty
  * string.
  *
  * @param {String} text
@@ -622,16 +630,20 @@ function getWarningGroupType(message) {
   if (isContentBlockingMessage(message)) {
     return MESSAGE_TYPE.CONTENT_BLOCKING_GROUP;
   }
 
   if (isTrackingProtectionMessage(message)) {
     return MESSAGE_TYPE.TRACKING_PROTECTION_GROUP;
   }
 
+  if (isCookieSameSiteMessage(message)) {
+    return MESSAGE_TYPE.COOKIE_SAMESITE_GROUP;
+  }
+
   return null;
 }
 
 /**
  * Returns a computed id given a message
  *
  * @param {ConsoleMessage} type: the message type, from MESSAGE_TYPE.
  * @param {Integer} innerWindowID: the message innerWindowID.
@@ -650,16 +662,17 @@ function getParentWarningGroupMessageId(
  * Returns true if the message is a warningGroup message (i.e. the "Header").
  * @param {ConsoleMessage} message
  * @returns {Boolean}
  */
 function isWarningGroup(message) {
   return (
     message.type === MESSAGE_TYPE.CONTENT_BLOCKING_GROUP ||
     message.type === MESSAGE_TYPE.TRACKING_PROTECTION_GROUP ||
+    message.type === MESSAGE_TYPE.COOKIE_SAMESITE_GROUP ||
     message.type === MESSAGE_TYPE.CORS_GROUP ||
     message.type === MESSAGE_TYPE.CSP_GROUP
   );
 }
 
 /**
  * Returns true if the message is a content blocking message.
  * @param {ConsoleMessage} message
@@ -680,16 +693,26 @@ function isContentBlockingMessage(messag
  * @param {ConsoleMessage} message
  * @returns {Boolean}
  */
 function isTrackingProtectionMessage(message) {
   const { category } = message;
   return category == "Tracking Protection";
 }
 
+/**
+ * Returns true if the message is a cookie message.
+ * @param {ConsoleMessage} message
+ * @returns {Boolean}
+ */
+function isCookieSameSiteMessage(message) {
+  const { category } = message;
+  return category == "cookieSameSite";
+}
+
 function getArrayTypeNames() {
   return [
     "Array",
     "Int8Array",
     "Uint8Array",
     "Int16Array",
     "Uint16Array",
     "Int32Array",
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -105,16 +105,19 @@ static const int64_t kCookiePurgeAge =
 
 #undef LIMIT
 #define LIMIT(x, low, high, default) \
   ((x) >= (low) && (x) <= (high) ? (x) : (default))
 
 #undef ADD_TEN_PERCENT
 #define ADD_TEN_PERCENT(i) static_cast<uint32_t>((i) + (i) / 10)
 
+#define CONSOLE_SAMESITE_CATEGORY NS_LITERAL_CSTRING("cookieSameSite")
+#define CONSOLE_GENERIC_CATEGORY NS_LITERAL_CSTRING("cookies")
+
 // default limits for the cookie list. these can be tuned by the
 // network.cookie.maxNumber and network.cookie.maxPerHost prefs respectively.
 static const uint32_t kMaxNumberOfCookies = 3000;
 static const uint32_t kMaxCookiesPerHost = 180;
 static const uint32_t kCookieQuotaPerHost = 150;
 static const uint32_t kMaxBytesPerCookie = 4096;
 static const uint32_t kMaxBytesPerPath = 1024;
 
@@ -3837,16 +3840,17 @@ bool nsCookieService::ParseAttributes(ns
         aCookieData.rawSameSite() = nsICookie::SAMESITE_STRICT;
         sameSiteSet = true;
       } else if (tokenValue.LowerCaseEqualsLiteral(kSameSiteNone)) {
         aCookieData.sameSite() = nsICookie::SAMESITE_NONE;
         aCookieData.rawSameSite() = nsICookie::SAMESITE_NONE;
         sameSiteSet = true;
       } else {
         LogMessageToConsole(aChannel, aHostURI, nsIScriptError::infoFlag,
+                            CONSOLE_GENERIC_CATEGORY,
                             NS_LITERAL_CSTRING("CookieSameSiteValueInvalid"),
                             aCookieData.name());
       }
     }
   }
 
   Telemetry::Accumulate(Telemetry::COOKIE_SAMESITE_SET_VS_UNSET,
                         sameSiteSet ? 1 : 0);
@@ -3856,51 +3860,56 @@ bool nsCookieService::ParseAttributes(ns
 
   // If same-site is set to 'none' but this is not a secure context, let's abort
   // the parsing.
   if (!aCookieData.isSecure() &&
       aCookieData.sameSite() == nsICookie::SAMESITE_NONE) {
     if (StaticPrefs::network_cookie_sameSite_laxByDefault() &&
         StaticPrefs::network_cookie_sameSite_noneRequiresSecure()) {
       LogMessageToConsole(aChannel, aHostURI, nsIScriptError::infoFlag,
+                          CONSOLE_SAMESITE_CATEGORY,
                           NS_LITERAL_CSTRING("CookieRejectedNonRequiresSecure"),
                           aCookieData.name());
       return newCookie;
     }
 
     // if sameSite=lax by default is disabled, we want to warn the user.
     LogMessageToConsole(
         aChannel, aHostURI, nsIScriptError::warningFlag,
+        CONSOLE_SAMESITE_CATEGORY,
         NS_LITERAL_CSTRING("CookieRejectedNonRequiresSecureForBeta"),
         aCookieData.name(), SAMESITE_MDN_URL);
   }
 
   if (aCookieData.rawSameSite() == nsICookie::SAMESITE_NONE &&
       aCookieData.sameSite() == nsICookie::SAMESITE_LAX) {
     if (StaticPrefs::network_cookie_sameSite_laxByDefault()) {
       LogMessageToConsole(aChannel, aHostURI, nsIScriptError::infoFlag,
+                          CONSOLE_SAMESITE_CATEGORY,
                           NS_LITERAL_CSTRING("CookieLaxForced"),
                           aCookieData.name());
     } else {
       LogMessageToConsole(aChannel, aHostURI, nsIScriptError::warningFlag,
+                          CONSOLE_SAMESITE_CATEGORY,
                           NS_LITERAL_CSTRING("CookieLaxForcedForBeta"),
                           aCookieData.name(), SAMESITE_MDN_URL);
     }
   }
 
   // Cookie accepted.
   aAcceptedByParser = true;
 
   MOZ_ASSERT(nsCookie::ValidateRawSame(aCookieData));
   return newCookie;
 }
 
 // static
 void nsCookieService::LogMessageToConsole(nsIChannel* aChannel, nsIURI* aURI,
                                           uint32_t aErrorFlags,
+                                          const nsACString& aCategory,
                                           const nsACString& aMsg,
                                           const nsACString& aCookieName,
                                           const nsAString& aMDNURL) {
   MOZ_ASSERT(aURI);
 
   nsCOMPtr<HttpBaseChannel> httpChannel = do_QueryInterface(aChannel);
   if (!httpChannel) {
     return;
@@ -3913,17 +3922,17 @@ void nsCookieService::LogMessageToConsol
   }
 
   AutoTArray<nsString, 1> params = {NS_ConvertUTF8toUTF16(aCookieName)};
 
   if (!aMDNURL.IsEmpty()) {
     params.AppendElement(aMDNURL);
   }
 
-  httpChannel->AddConsoleReport(aErrorFlags, NS_LITERAL_CSTRING("Security"),
+  httpChannel->AddConsoleReport(aErrorFlags, aCategory,
                                 nsContentUtils::eNECKO_PROPERTIES, uri, 0, 0,
                                 aMsg, params);
 }
 
 /******************************************************************************
  * nsCookieService impl:
  * private domain & permission compliance enforcement functions
  ******************************************************************************/
--- a/netwerk/cookie/nsCookieService.h
+++ b/netwerk/cookie/nsCookieService.h
@@ -345,17 +345,19 @@ class nsCookieService final : public nsI
                                         uint32_t* aCountFromHost);
 
  protected:
   nsresult RemoveCookiesFromExactHost(
       const nsACString& aHost,
       const mozilla::OriginAttributesPattern& aPattern);
 
   static void LogMessageToConsole(nsIChannel* aChannel, nsIURI* aURI,
-                                  uint32_t aErrorFlags, const nsACString& aMsg,
+                                  uint32_t aErrorFlags,
+                                  const nsACString& aCategory,
+                                  const nsACString& aMsg,
                                   const nsACString& aCookieName,
                                   const nsAString& aMDNURL = VoidString());
 
   // cached members.
   nsCOMPtr<nsICookiePermission> mPermissionService;
   nsCOMPtr<mozIThirdPartyUtil> mThirdPartyUtil;
   nsCOMPtr<nsIEffectiveTLDService> mTLDService;
   nsCOMPtr<nsIIDNService> mIDNService;