Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/net/cookies.js
2868 views
1
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview Functions for setting, getting and deleting cookies.
17
*
18
* @author [email protected] (Erik Arvidsson)
19
*/
20
21
22
goog.provide('goog.net.Cookies');
23
goog.provide('goog.net.cookies');
24
25
goog.require('goog.string');
26
27
28
29
/**
30
* A class for handling browser cookies.
31
* @param {?Document} context The context document to get/set cookies on.
32
* @constructor
33
* @final
34
*/
35
goog.net.Cookies = function(context) {
36
/**
37
* The context document to get/set cookies on. If no document context is
38
* passed, use a fake one with only the "cookie" attribute. This allows
39
* this class to be instantiated safely in web worker environments.
40
* @private {{cookie: string}}
41
*/
42
this.document_ = context || {cookie: ''};
43
};
44
45
46
/**
47
* Static constant for the size of cookies. Per the spec, there's a 4K limit
48
* to the size of a cookie. To make sure users can't break this limit, we
49
* should truncate long cookies at 3950 bytes, to be extra careful with dumb
50
* browsers/proxies that interpret 4K as 4000 rather than 4096.
51
* @type {number}
52
*/
53
goog.net.Cookies.MAX_COOKIE_LENGTH = 3950;
54
55
56
/**
57
* Returns true if cookies are enabled.
58
* @return {boolean} True if cookies are enabled.
59
*/
60
goog.net.Cookies.prototype.isEnabled = function() {
61
return navigator.cookieEnabled;
62
};
63
64
65
/**
66
* We do not allow '=', ';', or white space in the name.
67
*
68
* NOTE: The following are allowed by this method, but should be avoided for
69
* cookies handled by the server.
70
* - any name starting with '$'
71
* - 'Comment'
72
* - 'Domain'
73
* - 'Expires'
74
* - 'Max-Age'
75
* - 'Path'
76
* - 'Secure'
77
* - 'Version'
78
*
79
* @param {string} name Cookie name.
80
* @return {boolean} Whether name is valid.
81
*
82
* @see <a href="http://tools.ietf.org/html/rfc2109">RFC 2109</a>
83
* @see <a href="http://tools.ietf.org/html/rfc2965">RFC 2965</a>
84
*/
85
goog.net.Cookies.prototype.isValidName = function(name) {
86
return !(/[;=\s]/.test(name));
87
};
88
89
90
/**
91
* We do not allow ';' or line break in the value.
92
*
93
* Spec does not mention any illegal characters, but in practice semi-colons
94
* break parsing and line breaks truncate the name.
95
*
96
* @param {string} value Cookie value.
97
* @return {boolean} Whether value is valid.
98
*
99
* @see <a href="http://tools.ietf.org/html/rfc2109">RFC 2109</a>
100
* @see <a href="http://tools.ietf.org/html/rfc2965">RFC 2965</a>
101
*/
102
goog.net.Cookies.prototype.isValidValue = function(value) {
103
return !(/[;\r\n]/.test(value));
104
};
105
106
107
/**
108
* Sets a cookie. The max_age can be -1 to set a session cookie. To remove and
109
* expire cookies, use remove() instead.
110
*
111
* Neither the {@code name} nor the {@code value} are encoded in any way. It is
112
* up to the callers of {@code get} and {@code set} (as well as all the other
113
* methods) to handle any possible encoding and decoding.
114
*
115
* @throws {!Error} If the {@code name} fails #goog.net.cookies.isValidName.
116
* @throws {!Error} If the {@code value} fails #goog.net.cookies.isValidValue.
117
*
118
* @param {string} name The cookie name.
119
* @param {string} value The cookie value.
120
* @param {number=} opt_maxAge The max age in seconds (from now). Use -1 to
121
* set a session cookie. If not provided, the default is -1
122
* (i.e. set a session cookie).
123
* @param {?string=} opt_path The path of the cookie. If not present then this
124
* uses the full request path.
125
* @param {?string=} opt_domain The domain of the cookie, or null to not
126
* specify a domain attribute (browser will use the full request host name).
127
* If not provided, the default is null (i.e. let browser use full request
128
* host name).
129
* @param {boolean=} opt_secure Whether the cookie should only be sent over
130
* a secure channel.
131
*/
132
goog.net.Cookies.prototype.set = function(
133
name, value, opt_maxAge, opt_path, opt_domain, opt_secure) {
134
if (!this.isValidName(name)) {
135
throw Error('Invalid cookie name "' + name + '"');
136
}
137
if (!this.isValidValue(value)) {
138
throw Error('Invalid cookie value "' + value + '"');
139
}
140
141
if (!goog.isDef(opt_maxAge)) {
142
opt_maxAge = -1;
143
}
144
145
var domainStr = opt_domain ? ';domain=' + opt_domain : '';
146
var pathStr = opt_path ? ';path=' + opt_path : '';
147
var secureStr = opt_secure ? ';secure' : '';
148
149
var expiresStr;
150
151
// Case 1: Set a session cookie.
152
if (opt_maxAge < 0) {
153
expiresStr = '';
154
155
// Case 2: Remove the cookie.
156
// Note: We don't tell people about this option in the function doc because
157
// we prefer people to use remove() to remove cookies.
158
} else if (opt_maxAge == 0) {
159
// Note: Don't use Jan 1, 1970 for date because NS 4.76 will try to convert
160
// it to local time, and if the local time is before Jan 1, 1970, then the
161
// browser will ignore the Expires attribute altogether.
162
var pastDate = new Date(1970, 1 /*Feb*/, 1); // Feb 1, 1970
163
expiresStr = ';expires=' + pastDate.toUTCString();
164
165
// Case 3: Set a persistent cookie.
166
} else {
167
var futureDate = new Date(goog.now() + opt_maxAge * 1000);
168
expiresStr = ';expires=' + futureDate.toUTCString();
169
}
170
171
this.setCookie_(
172
name + '=' + value + domainStr + pathStr + expiresStr + secureStr);
173
};
174
175
176
/**
177
* Returns the value for the first cookie with the given name.
178
* @param {string} name The name of the cookie to get.
179
* @param {string=} opt_default If not found this is returned instead.
180
* @return {string|undefined} The value of the cookie. If no cookie is set this
181
* returns opt_default or undefined if opt_default is not provided.
182
*/
183
goog.net.Cookies.prototype.get = function(name, opt_default) {
184
var nameEq = name + '=';
185
var parts = this.getParts_();
186
for (var i = 0, part; i < parts.length; i++) {
187
part = goog.string.trim(parts[i]);
188
// startsWith
189
if (part.lastIndexOf(nameEq, 0) == 0) {
190
return part.substr(nameEq.length);
191
}
192
if (part == name) {
193
return '';
194
}
195
}
196
return opt_default;
197
};
198
199
200
/**
201
* Removes and expires a cookie.
202
* @param {string} name The cookie name.
203
* @param {string=} opt_path The path of the cookie, or null to expire a cookie
204
* set at the full request path. If not provided, the default is '/'
205
* (i.e. path=/).
206
* @param {string=} opt_domain The domain of the cookie, or null to expire a
207
* cookie set at the full request host name. If not provided, the default is
208
* null (i.e. cookie at full request host name).
209
* @return {boolean} Whether the cookie existed before it was removed.
210
*/
211
goog.net.Cookies.prototype.remove = function(name, opt_path, opt_domain) {
212
var rv = this.containsKey(name);
213
this.set(name, '', 0, opt_path, opt_domain);
214
return rv;
215
};
216
217
218
/**
219
* Gets the names for all the cookies.
220
* @return {Array<string>} An array with the names of the cookies.
221
*/
222
goog.net.Cookies.prototype.getKeys = function() {
223
return this.getKeyValues_().keys;
224
};
225
226
227
/**
228
* Gets the values for all the cookies.
229
* @return {Array<string>} An array with the values of the cookies.
230
*/
231
goog.net.Cookies.prototype.getValues = function() {
232
return this.getKeyValues_().values;
233
};
234
235
236
/**
237
* @return {boolean} Whether there are any cookies for this document.
238
*/
239
goog.net.Cookies.prototype.isEmpty = function() {
240
return !this.getCookie_();
241
};
242
243
244
/**
245
* @return {number} The number of cookies for this document.
246
*/
247
goog.net.Cookies.prototype.getCount = function() {
248
var cookie = this.getCookie_();
249
if (!cookie) {
250
return 0;
251
}
252
return this.getParts_().length;
253
};
254
255
256
/**
257
* Returns whether there is a cookie with the given name.
258
* @param {string} key The name of the cookie to test for.
259
* @return {boolean} Whether there is a cookie by that name.
260
*/
261
goog.net.Cookies.prototype.containsKey = function(key) {
262
// substring will return empty string if the key is not found, so the get
263
// function will only return undefined
264
return goog.isDef(this.get(key));
265
};
266
267
268
/**
269
* Returns whether there is a cookie with the given value. (This is an O(n)
270
* operation.)
271
* @param {string} value The value to check for.
272
* @return {boolean} Whether there is a cookie with that value.
273
*/
274
goog.net.Cookies.prototype.containsValue = function(value) {
275
// this O(n) in any case so lets do the trivial thing.
276
var values = this.getKeyValues_().values;
277
for (var i = 0; i < values.length; i++) {
278
if (values[i] == value) {
279
return true;
280
}
281
}
282
return false;
283
};
284
285
286
/**
287
* Removes all cookies for this document. Note that this will only remove
288
* cookies from the current path and domain. If there are cookies set using a
289
* subpath and/or another domain these will still be there.
290
*/
291
goog.net.Cookies.prototype.clear = function() {
292
var keys = this.getKeyValues_().keys;
293
for (var i = keys.length - 1; i >= 0; i--) {
294
this.remove(keys[i]);
295
}
296
};
297
298
299
/**
300
* Private helper function to allow testing cookies without depending on the
301
* browser.
302
* @param {string} s The cookie string to set.
303
* @private
304
*/
305
goog.net.Cookies.prototype.setCookie_ = function(s) {
306
this.document_.cookie = s;
307
};
308
309
310
/**
311
* Private helper function to allow testing cookies without depending on the
312
* browser. IE6 can return null here.
313
* @return {string} Returns the {@code document.cookie}.
314
* @private
315
*/
316
goog.net.Cookies.prototype.getCookie_ = function() {
317
return this.document_.cookie;
318
};
319
320
321
/**
322
* @return {!Array<string>} The cookie split on semi colons.
323
* @private
324
*/
325
goog.net.Cookies.prototype.getParts_ = function() {
326
return (this.getCookie_() || '').split(';');
327
};
328
329
330
/**
331
* Gets the names and values for all the cookies.
332
* @return {!{keys:!Array<string>, values:!Array<string>}} An object with keys
333
* and values.
334
* @private
335
*/
336
goog.net.Cookies.prototype.getKeyValues_ = function() {
337
var parts = this.getParts_();
338
var keys = [], values = [], index, part;
339
for (var i = 0; i < parts.length; i++) {
340
part = goog.string.trim(parts[i]);
341
index = part.indexOf('=');
342
343
if (index == -1) { // empty name
344
keys.push('');
345
values.push(part);
346
} else {
347
keys.push(part.substring(0, index));
348
values.push(part.substring(index + 1));
349
}
350
}
351
return {keys: keys, values: values};
352
};
353
354
355
// TODO(closure-team): This should be a singleton getter instead of a static
356
// instance.
357
/**
358
* A static default instance.
359
* @const {!goog.net.Cookies}
360
*/
361
goog.net.cookies =
362
new goog.net.Cookies(typeof document == 'undefined' ? null : document);
363
364
365
/**
366
* Define the constant on the instance in order not to break many references to
367
* it.
368
* @type {number}
369
* @deprecated Use goog.net.Cookies.MAX_COOKIE_LENGTH instead.
370
*/
371
goog.net.cookies.MAX_COOKIE_LENGTH = goog.net.Cookies.MAX_COOKIE_LENGTH;
372
373