Cap lifetime of persistent cookies created client-side through document.cookie
[WebKit-https.git] / LayoutTests / http / tests / cookies / resources / cookie-utilities.js
1 if (self.testRunner)
2     testRunner.waitUntilDone();
3
4 var g_childWindow;
5 var g_cachedCookies;
6 var g_baseURLWhenFetchingCookies = "";
7 var g_baseDocumentWhenFetchingDOMCookies;
8
9 function createCookie(name, value, additionalProperties)
10 {
11     let cookie = `${name}=${value}`;
12     for (let propertyName in additionalProperties) {
13         cookie += `; ${propertyName}`;
14         let propertyValue = additionalProperties[propertyName];
15         if (propertyValue != undefined)
16             cookie += "=" + propertyValue;
17     }
18     return cookie;
19 }
20
21 function setBaseDocumentWhenFetchingDOMCookies(aDocument)
22 {
23     g_baseDocumentWhenFetchingDOMCookies = aDocument;
24 }
25
26 function setDOMCookie(name, value, additionalProperties={})
27 {
28     g_baseDocumentWhenFetchingDOMCookies.cookie = createCookie(name, value, additionalProperties);
29 }
30
31 function getDOMCookies()
32 {
33     if (!g_baseDocumentWhenFetchingDOMCookies)
34         g_baseDocumentWhenFetchingDOMCookies = document;
35     if (!g_baseDocumentWhenFetchingDOMCookies.cookie)
36         return {};
37     let cookies = g_baseDocumentWhenFetchingDOMCookies.cookie.split("; ");
38     let result = {};
39     for (let keyAndValuePair of cookies) {
40         let [key, value] = keyAndValuePair.split("=");
41         result[key] = value;
42     }
43    return result;
44 }
45
46 async function setCookie(name, value, additionalProperties={})
47 {
48     invalidateCachedCookies();
49
50     let cookie = createCookie(name, value, additionalProperties);
51     let promise = new Promise((resolved, rejected) => {
52         let xhr = new XMLHttpRequest;
53         xhr.open("GET", "/cookies/resources/setCookies.cgi");
54         xhr.setRequestHeader("SET-COOKIE", cookie);
55         xhr.onload = () => resolved(xhr.responseText);
56         xhr.onerror = rejected;
57         xhr.send(null);
58     });
59     return promise;
60 }
61
62 function disableSetAlwaysAcceptCookies() {
63     if (window.testRunner)
64         testRunner.setAlwaysAcceptCookies(false);
65 }
66
67 async function resetCookies(urls)
68 {
69     let testingURLs = [
70         "http://127.0.0.1:8000",
71         "http://localhost:8000",
72     ];
73
74     urls = urls || testingURLs;
75     console.assert(urls.length);
76
77     function setUp() {
78         return new Promise((resolve) => {
79             if (window.testRunner) {
80                 testRunner.setCanOpenWindows(true);
81                 testRunner.setAlwaysAcceptCookies(true);
82                 testRunner.setPopupBlockingEnabled(false);
83             }
84             resolve();
85         });
86     }
87
88     function cleanUp() {
89         return new Promise((resolve) => {
90             disableSetAlwaysAcceptCookies();
91             g_childWindow.close();
92             g_childWindow = null;
93             resolve();
94         });
95     }
96
97     let promise = setUp();
98     for (let url of urls) {
99         promise = promise.then(() => {
100             return new Promise((resolve, reject) => {
101                 // FIXME: For some reason we get a SecurityError when passing childWindow to resolve() in Safari Version 11.0.3 (13604.5.6)
102                 // and not in Chrome Canary 67.0.3390.0 (why?). As a workaround, store the child window reference in a global variable.
103                 window.addEventListener("message", (messageEvent) => resolve(messageEvent), {capture: true, once: true});
104                 g_childWindow = window.open(url + "/cookies/resources/cookie-utility.php?queryfunction=deleteCookiesAndPostMessage", "reset");
105                 if (!g_childWindow)
106                     reject(null);
107             });
108         });
109     }
110     return promise.then(cleanUp);
111 }
112
113 async function resetCookiesForCurrentOrigin()
114 {
115     invalidateCachedCookies();
116
117     let promise = new Promise((resolved, rejected) => {
118         let xhr = new XMLHttpRequest;
119         xhr.open("GET", "/cookies/resources/cookie-utility.php?queryfunction=deleteCookies");
120         xhr.onload = (progressEvent) => {
121             disableSetAlwaysAcceptCookies();
122             resolved(progressEvent);
123         };
124         xhr.onerror = (progressEvent) => {
125             disableSetAlwaysAcceptCookies();
126             rejected(progressEvent);
127         };
128
129         if (window.testRunner)
130             testRunner.setAlwaysAcceptCookies(true);
131
132         xhr.send(null);
133     });
134     return promise;
135 }
136
137 function setBaseURLWhenFetchingCookies(baseURLWhenFetchingCookies)
138 {
139     g_baseURLWhenFetchingCookies = baseURLWhenFetchingCookies;
140 }
141
142 function invalidateCachedCookies()
143 {
144     g_cachedCookies = null;
145 }
146
147 function _setCachedCookiesJSON(cookies)
148 {
149     g_cachedCookies = JSON.parse(cookies);
150 }
151
152 async function getCookies()
153 {
154     if (g_cachedCookies)
155         return g_cachedCookies;
156
157     let promise = new Promise((resolved, rejected) => {
158         let xhr = new XMLHttpRequest;
159         xhr.open("GET", `${g_baseURLWhenFetchingCookies}/cookies/resources/echo-json.php`);
160         xhr.onload = () => resolved(xhr.responseText ? JSON.parse(xhr.responseText) : {});
161         xhr.onerror = () => rejected({});
162         xhr.send(null);
163     });
164     g_cachedCookies = await promise;
165     return g_cachedCookies;
166 }
167
168 async function shouldNotHaveCookie(name)
169 {
170     let cookies = await getCookies();
171     let value = cookies[name];
172     if (value == undefined)
173         testPassed(`Do not have cookie "${name}".`);
174     else
175         testFailed(`Should not have cookie "${name}". But do with value ${value}.`);
176 }
177
178 async function shouldHaveCookie(name)
179 {
180     let cookies = await getCookies();
181     let value = cookies[name];
182     if (value == undefined)
183         testFailed(`Should have cookie "${name}". But do not.`);
184     else
185         testPassed(`Has cookie "${name}".`);
186 }
187
188 async function shouldHaveCookieWithValue(name, expectedValue)
189 {
190     console.assert(expectedValue !== undefined);
191     let cookies = await getCookies();
192     let value = cookies[name];
193     if (value == undefined)
194         testFailed(`Should have cookie "${name}". But do not.`);
195     else if (value === expectedValue)
196         testPassed(`Has cookie "${name}" with value ${value}.`);
197     else
198         testFailed(`Cookie "${name}" should have value ${expectedValue}. Was ${value}.`);
199 }
200
201 function shouldNotHaveDOMCookie(name)
202 {
203     let cookies = getDOMCookies();
204     let value = cookies[name];
205     if (value == undefined)
206         testPassed(`Do not have DOM cookie "${name}".`);
207     else
208         testFailed(`Should not have DOM cookie "${name}". But do with value ${value}.`);
209 }
210
211 function shouldHaveDOMCookie(name)
212 {
213     let cookies = getDOMCookies();
214     let value = cookies[name];
215     if (value == undefined)
216         testFailed(`Should have DOM cookie "${name}". But do not.`);
217     else
218         testPassed(`Has DOM cookie "${name}".`);
219 }
220
221 function shouldHaveDOMCookieWithValue(name, expectedValue)
222 {
223     console.assert(expectedValue !== undefined);
224     let cookies = getDOMCookies();
225     let value = cookies[name];
226     if (value == undefined)
227         testFailed(`Should have DOM cookie "${name}". But do not.`);
228     else if (value === expectedValue)
229         testPassed(`Has DOM cookie "${name}" with value ${value}.`);
230     else
231         testFailed(`DOM cookie "${name}" should have value ${expectedValue}. Was ${value}.`);
232 }
233
234 function setCookieUsingWebSocketFromHost(host)
235 {
236     var promise = new Promise(resolve => {
237         var websocket = new WebSocket(`ws://${host}:8880/websocket/tests/hybi/cookie?set`);
238         websocket.onclose = () => resolve();
239     });
240     return promise;
241 }
242
243 function createExpiresDateFromMaxAge(maxAgeInSeconds)
244 {
245     let date = new Date();
246     date.setTime(date.getTime() + (maxAgeInSeconds * 1000));
247     return date.toUTCString();
248 }