Skip to content

Commit 7923b9b

Browse files
committed
AG-41048 Fix 'trusted-set-cookie-reload' — prevent infinite reload for constantly changing values. #489
Squashed commit of the following: commit 9963438 Author: Adam Wróblewski <[email protected]> Date: Wed Jun 18 12:36:37 2025 +0200 Update comment commit c2a9eab Author: Adam Wróblewski <[email protected]> Date: Wed Jun 18 10:18:50 2025 +0200 Move timeKeywords to isCookieSetWithValue commit e44de75 Author: Adam Wróblewski <[email protected]> Date: Tue Jun 17 13:10:34 2025 +0200 Add comments Change variable name to UPPER_SNAKE_CASE format commit 0725ec3 Author: Adam Wróblewski <[email protected]> Date: Wed Jun 11 14:11:21 2025 +0200 Fix 'trusted-set-cookie-reload' — prevent infinite reload for constantly changing values
1 parent 03651fa commit 7923b9b

File tree

4 files changed

+67
-1
lines changed

4 files changed

+67
-1
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ The format is based on [Keep a Changelog], and this project adheres to [Semantic
1010
<!-- TODO: change `@added unknown` tag due to the actual version -->
1111
<!-- during new scriptlets or redirects releasing -->
1212

13+
## [Unreleased]
14+
15+
### Fixed
16+
17+
- `trusted-set-cookie-reload` scriptlet infinite page reloading when cookie with time keyword is used [#489].
18+
19+
[Unreleased]: https://github.com/AdguardTeam/Scriptlets/compare/v2.2.7...HEAD
20+
[#489]: https://github.com/AdguardTeam/Scriptlets/issues/489
21+
1322
<!-- v2.2.6 is the same as v2.2.7 -->
1423
## [v2.2.7] - 2025-06-04
1524

src/helpers/cookie-utils.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,11 @@ export const parseCookieString = (cookieString: string): CookieData => {
201201
* @param value value argument of *set-cookie-* scriptlets
202202
* @returns if cookie is already set
203203
*/
204-
export const isCookieSetWithValue = (cookieString: string, name: string, value: string): boolean => {
204+
export const isCookieSetWithValue = (
205+
cookieString: string,
206+
name: string,
207+
value: string,
208+
): boolean => {
205209
return cookieString.split(';')
206210
.some((cookieStr) => {
207211
const pos = cookieStr.indexOf('=');
@@ -211,6 +215,30 @@ export const isCookieSetWithValue = (cookieString: string, name: string, value:
211215
const cookieName = cookieStr.slice(0, pos).trim();
212216
const cookieValue = cookieStr.slice(pos + 1).trim();
213217

218+
// If required, remember to sync new time keywords with the "parseKeywordValue" function
219+
const timeKeywords = new Set([
220+
'$now$',
221+
'$currentDate$',
222+
'$currentISODate$',
223+
]);
224+
const isValueTimeKeyword = timeKeywords.has(value);
225+
226+
// Prevent webpage reloading when cookie value is a time keyword
227+
// https://github.com/AdguardTeam/Scriptlets/issues/489
228+
if (isValueTimeKeyword) {
229+
// The time after which the website will reload (1 day)
230+
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
231+
const now = Date.now();
232+
// Convert cookie value to milliseconds
233+
const cookieValueMs = /^\d+$/.test(cookieValue)
234+
? parseInt(cookieValue, 10)
235+
: new Date(cookieValue).getTime();
236+
237+
// If cookie value is greater than now minus one day, return true,
238+
// otherwise return false and new cookie should be set
239+
return name === cookieName && cookieValueMs > now - ONE_DAY_MS;
240+
}
241+
214242
return name === cookieName && value === cookieValue;
215243
});
216244
};

src/helpers/parse-keyword-value.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
*/
1212
export const parseKeywordValue = (rawValue: string): string => {
1313
// !IMPORTANT: Do not move constants outside of this function
14+
// Remember to add new keywords to "isCookieSetWithValue" function in "cookie-utils", if required
15+
// https://github.com/AdguardTeam/Scriptlets/issues/489
1416
const NOW_VALUE_KEYWORD = '$now$';
1517
const CURRENT_DATE_KEYWORD = '$currentDate$';
1618
const CURRENT_ISO_DATE_KEYWORD = '$currentISODate$';

tests/scriptlets/trusted-set-cookie-reload.spec.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,33 @@ describe('Test trusted-set-cookie-reload scriptlet', () => {
8484
clearCookie(cName);
8585
});
8686

87+
test('Set cookie with current ISO date value and reload', () => {
88+
const cName = '__test-cookie_current_date_reload';
89+
const cValue = '$currentISODate$';
90+
const expiresSec = '';
91+
const cPath = '/';
92+
93+
trustedSetCookieReload(sourceParams, cName, cValue, expiresSec, cPath);
94+
95+
// Some time will pass between calling scriptlet
96+
// and jest running test
97+
const cookieValue = parseCookieString(document.cookie)[cName];
98+
// Check only day, month and year
99+
const currentISODate = new Date().toISOString().split('T')[0];
100+
const dateDiff = cookieValue.split('T')[0];
101+
102+
expect(dateDiff.startsWith(currentISODate)).toBeTruthy();
103+
expect(document.cookie.includes(cName)).toBeTruthy();
104+
expect(window.location.reload).toHaveBeenCalledTimes(1);
105+
expect(window.hit).toBe('FIRED');
106+
107+
// Run scriptlet again to check if reload is called
108+
trustedSetCookieReload(sourceParams, cName, cValue, expiresSec, cPath);
109+
expect(window.location.reload).toHaveBeenCalledTimes(1);
110+
111+
clearCookie(cName);
112+
});
113+
87114
test('Set cookie string', () => {
88115
const cName = '__test-cookie_OK';
89116
const cValue = 'OK';

0 commit comments

Comments
 (0)