Repository: electron/electron
Pull request: fix: handle exclude aliasing in InclusionStatusToString()

#### Description of Change

Upstream added a new cookie exclusion type `EXCLUDE_ALIASING` last December in https://chromium-review.googlesource.com/c/chromium/src/+/6071023 but until now we weren't handling it in `InclusionStatusToString()`.

This PR:

- Adds a human-readable string for `EXCLUDE_ALIASING`
- Adds a `static_assert()` to ensure that if more reasons are added in the future, the compiler will give us a heads-up
- Uses a `std::ostringstream` to make building the `reason` string a little more efficient

#### Checklist

- [x] PR description included and stakeholders cc'd
- [x] `npm test` passes
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/main/README.md#examples).

#### Release Notes

Notes: none.

Changed files:
filename: shell/browser/api/electron_api_cookies.cc
patch: @@ -4,10 +4,12 @@
 
 #include "shell/browser/api/electron_api_cookies.h"
 
+#include <sstream>
 #include <string>
 #include <string_view>
 #include <utility>
 
+#include "base/containers/fixed_flat_map.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "content/public/browser/browser_context.h"
@@ -176,94 +178,96 @@ base::Time ParseTimeProperty(const std::optional<double>& value) {
 
 const std::string InclusionStatusToString(net::CookieInclusionStatus status) {
   // See net/cookies/cookie_inclusion_status.h for cookie error descriptions.
-  constexpr std::array<
-      std::pair<net::CookieInclusionStatus::ExclusionReason, std::string_view>,
-      net::CookieInclusionStatus::ExclusionReason::NUM_EXCLUSION_REASONS>
-      exclusion_reasons = {
-          {{net::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
+  using Status = net::CookieInclusionStatus;
+  using Reason = net::CookieInclusionStatus::ExclusionReason;
+  static constexpr auto Reasons =
+      base::MakeFixedFlatMap<Reason, std::string_view>(
+          {{Status::EXCLUDE_UNKNOWN_ERROR, "Unknown error"},
+           {Status::EXCLUDE_HTTP_ONLY,
             "The cookie was HttpOnly, but the attempted access was through a "
             "non-HTTP API."},
-           {net::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
+           {Status::EXCLUDE_SECURE_ONLY,
             "The cookie was Secure, but the URL was not allowed to access "
             "Secure cookies."},
-           {net::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH,
+           {Status::EXCLUDE_DOMAIN_MISMATCH,
             "The cookie's domain attribute did not match the domain of the URL "
             "attempting access."},
-           {net::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH,
+           {Status::EXCLUDE_NOT_ON_PATH,
             "The cookie's path attribute did not match the path of the URL "
             "attempting access."},
-           {net::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT,
+           {Status::EXCLUDE_SAMESITE_STRICT,
             "The cookie had SameSite=Strict, and the attempted access did not "
             "have an appropriate SameSiteCookieContext"},
-           {net::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
+           {Status::EXCLUDE_SAMESITE_LAX,
             "The cookie had SameSite=Lax, and the attempted access did not "
             "have "
             "an appropriate SameSiteCookieContext"},
-           {net::CookieInclusionStatus::
-                EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
+           {Status::EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
             "The cookie did not specify a SameSite attribute, and therefore "
-            "was "
-            "treated as if it were SameSite=Lax, and the attempted access did "
-            "not have an appropriate SameSiteCookieContext."},
-           {net::CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE,
+            "was treated as if it were SameSite=Lax, and the attempted "
+            "access did not have an appropriate SameSiteCookieContext."},
+           {Status::EXCLUDE_SAMESITE_NONE_INSECURE,
             "The cookie specified SameSite=None, but it was not Secure."},
-           {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
+           {Status::EXCLUDE_USER_PREFERENCES,
             "Caller did not allow access to the cookie."},
-           {net::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE,
+           {Status::EXCLUDE_FAILURE_TO_STORE,
             "The cookie was malformed and could not be stored"},
-           {net::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME,
+           {Status::EXCLUDE_NONCOOKIEABLE_SCHEME,
             "Attempted to set a cookie from a scheme that does not support "
             "cookies."},
-           {net::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+           {Status::EXCLUDE_OVERWRITE_SECURE,
             "The cookie would have overwritten a Secure cookie, and was not "
             "allowed to do so."},
-           {net::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY,
+           {Status::EXCLUDE_OVERWRITE_HTTP_ONLY,
             "The cookie would have overwritten an HttpOnly cookie, and was not "
             "allowed to do so."},
-           {net::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN,
+           {Status::EXCLUDE_INVALID_DOMAIN,
             "The cookie was set with an invalid Domain attribute."},
-           {net::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
+           {Status::EXCLUDE_INVALID_PREFIX,
             "The cookie was set with an invalid __Host- or __Secure- prefix."},
-           {net::CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED,
+           {Status::EXCLUDE_INVALID_PARTITIONED,
             "Cookie was set with an invalid Partitioned attribute, which is "
             "only valid if the cookie has a __Host- prefix."},
-           {net::CookieInclusionStatus::
-                EXCLUDE_NAME_VALUE_PAIR_EXCEEDS_MAX_SIZE,
+           {Status::EXCLUDE_NAME_VALUE_PAIR_EXCEEDS_MAX_SIZE,
             "The cookie exceeded the name/value pair size limit."},
-           {net::CookieInclusionStatus::
-                EXCLUDE_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE,
+           {Status::EXCLUDE_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE,
             "Cookie exceeded the attribute size limit."},
-           {net::CookieInclusionStatus::EXCLUDE_DOMAIN_NON_ASCII,
+           {Status::EXCLUDE_DOMAIN_NON_ASCII,
             "The cookie was set with a Domain attribute containing non ASCII "
             "characters."},
-           {net::CookieInclusionStatus::
-                EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET,
+           {Status::EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET,
             "The cookie is blocked by third-party cookie blocking but the two "
             "sites are in the same First-Party Set"},
-           {net::CookieInclusionStatus::EXCLUDE_PORT_MISMATCH,
+           {Status::EXCLUDE_PORT_MISMATCH,
             "The cookie's source_port did not match the port of the request."},
-           {net::CookieInclusionStatus::EXCLUDE_SCHEME_MISMATCH,
+           {Status::EXCLUDE_SCHEME_MISMATCH,
             "The cookie's source_scheme did not match the scheme of the "
             "request."},
-           {net::CookieInclusionStatus::EXCLUDE_SHADOWING_DOMAIN,
+           {Status::EXCLUDE_SHADOWING_DOMAIN,
             "The cookie is a domain cookie and has the same name as an origin "
             "cookie on this origin."},
-           {net::CookieInclusionStatus::EXCLUDE_DISALLOWED_CHARACTER,
+           {Status::EXCLUDE_DISALLOWED_CHARACTER,
             "The cookie contains ASCII control characters"},
-           {net::CookieInclusionStatus::EXCLUDE_THIRD_PARTY_PHASEOUT,
+           {Status::EXCLUDE_THIRD_PARTY_PHASEOUT,
             "The cookie is blocked for third-party cookie phaseout."},
-           {net::CookieInclusionStatus::EXCLUDE_NO_COOKIE_CONTENT,
-            "The cookie contains no content or only whitespace."}}};
-
-  std::string reason = "Failed to set cookie - ";
-  for (const auto& [val, str] : exclusion_reasons) {
+           {Status::EXCLUDE_NO_COOKIE_CONTENT,
+            "The cookie contains no content or only whitespace."},
+           {Status::EXCLUDE_ALIASING,
+            "Cookie aliases that of another with a different source_port or "
+            "source scheme. I.e.: Two or more cookies share the same name "
+            "but have different ports/schemes."}});
+  static_assert(Reasons.size() == Status::NUM_EXCLUSION_REASONS);
+
+  std::ostringstream reason;
+  reason << "Failed to set cookie - ";
+  for (const auto& [val, str] : Reasons) {
     if (status.HasExclusionReason(val)) {
-      reason += str;
+      reason << str;
     }
   }
 
-  reason += status.GetDebugString();
-  return reason;
+  reason << status.GetDebugString();
+  return reason.str();
 }
 
 std::string StringToCookieSameSite(const std::string* str_ptr,