Browse Source

refactor: revert url::DomainIs() for cookie domains (#44154)

trop[bot] 6 months ago
parent
commit
4e6e77d696
3 changed files with 21 additions and 57 deletions
  1. 1 1
      docs/api/cookies.md
  2. 20 7
      shell/browser/api/electron_api_cookies.cc
  3. 0 49
      spec/api-session-spec.ts

+ 1 - 1
docs/api/cookies.md

@@ -74,7 +74,7 @@ The following methods are available on instances of `Cookies`:
     `url`. Empty implies retrieving cookies of all URLs.
   * `name` string (optional) - Filters cookies by name.
   * `domain` string (optional) - Retrieves cookies whose domains match or are
-    subdomains of `domain`.
+    subdomains of `domains`.
   * `path` string (optional) - Retrieves cookies whose path matches `path`.
   * `secure` boolean (optional) - Filters cookies by their Secure property.
   * `session` boolean (optional) - Filters out session or persistent cookies.

+ 20 - 7
shell/browser/api/electron_api_cookies.cc

@@ -30,7 +30,6 @@
 #include "shell/common/gin_helper/dictionary.h"
 #include "shell/common/gin_helper/object_template_builder.h"
 #include "shell/common/gin_helper/promise.h"
-#include "url/url_util.h"
 
 namespace gin {
 
@@ -101,12 +100,25 @@ namespace electron::api {
 
 namespace {
 
-bool DomainIs(std::string_view host, const std::string_view domain) {
-  // Strip any leading '.' character from the input cookie domain.
-  if (host.starts_with('.'))
-    host.remove_prefix(1);
+// Returns whether |domain| matches |filter|.
+bool MatchesDomain(std::string filter, const std::string& domain) {
+  // Add a leading '.' character to the filter domain if it doesn't exist.
+  if (net::cookie_util::DomainIsHostOnly(filter))
+    filter.insert(0, ".");
 
-  return url::DomainIs(host, domain);
+  std::string sub_domain(domain);
+  // Strip any leading '.' character from the input cookie domain.
+  if (!net::cookie_util::DomainIsHostOnly(sub_domain))
+    sub_domain = sub_domain.substr(1);
+
+  // Now check whether the domain argument is a subdomain of the filter domain.
+  for (sub_domain.insert(0, "."); sub_domain.length() >= filter.length();) {
+    if (sub_domain == filter)
+      return true;
+    const size_t next_dot = sub_domain.find('.', 1);  // Skip over leading dot.
+    sub_domain.erase(0, next_dot);
+  }
+  return false;
 }
 
 // Returns whether |cookie| matches |filter|.
@@ -117,7 +129,8 @@ bool MatchesCookie(const base::Value::Dict& filter,
     return false;
   if ((str = filter.FindString("path")) && *str != cookie.Path())
     return false;
-  if ((str = filter.FindString("domain")) && !DomainIs(cookie.Domain(), *str))
+  if ((str = filter.FindString("domain")) &&
+      !MatchesDomain(*str, cookie.Domain()))
     return false;
   std::optional<bool> secure_filter = filter.FindBool("secure");
   if (secure_filter && *secure_filter != cookie.SecureAttribute())

+ 0 - 49
spec/api-session-spec.ts

@@ -5,7 +5,6 @@ import { expect } from 'chai';
 import * as send from 'send';
 
 import * as ChildProcess from 'node:child_process';
-import * as crypto from 'node:crypto';
 import { once } from 'node:events';
 import * as fs from 'node:fs';
 import * as http from 'node:http';
@@ -130,54 +129,6 @@ describe('session module', () => {
       expect(cs.some(c => c.name === name && c.value === value)).to.equal(true);
     });
 
-    it('does not match on empty domain filter strings', async () => {
-      const { cookies } = session.defaultSession;
-      const name = crypto.randomBytes(20).toString('hex');
-      const value = '1';
-      const url = 'https://microsoft.com/';
-
-      await cookies.set({ url, name, value });
-      const cs = await cookies.get({ domain: '' });
-      expect(cs.some(c => c.name === name && c.value === value)).to.equal(false);
-      cookies.remove(url, name);
-    });
-
-    it('gets domain-equal cookies', async () => {
-      const { cookies } = session.defaultSession;
-      const name = crypto.randomBytes(20).toString('hex');
-      const value = '1';
-      const url = 'https://microsoft.com/';
-
-      await cookies.set({ url, name, value });
-      const cs = await cookies.get({ domain: 'microsoft.com' });
-      expect(cs.some(c => c.name === name && c.value === value)).to.equal(true);
-      cookies.remove(url, name);
-    });
-
-    it('gets domain-inclusive cookies', async () => {
-      const { cookies } = session.defaultSession;
-      const name = crypto.randomBytes(20).toString('hex');
-      const value = '1';
-      const url = 'https://subdomain.microsoft.com/';
-
-      await cookies.set({ url, name, value });
-      const cs = await cookies.get({ domain: 'microsoft.com' });
-      expect(cs.some(c => c.name === name && c.value === value)).to.equal(true);
-      cookies.remove(url, name);
-    });
-
-    it('omits domain-exclusive cookies', async () => {
-      const { cookies } = session.defaultSession;
-      const name = crypto.randomBytes(20).toString('hex');
-      const value = '1';
-      const url = 'https://microsoft.com';
-
-      await cookies.set({ url, name, value });
-      const cs = await cookies.get({ domain: 'subdomain.microsoft.com' });
-      expect(cs.some(c => c.name === name && c.value === value)).to.equal(false);
-      cookies.remove(url, name);
-    });
-
     it('rejects when setting a cookie with missing required fields', async () => {
       const { cookies } = session.defaultSession;
       const name = '1';