1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6* Test whether the given domain is valid for a cookie.
7*
8* @param {string} domain Domain for a cookie.
9* @return {boolean} True if the domain is valid, otherwise false.
10*/
11function isDomainValid(domain) {
12  var dummyCookie = 'ChromeDriverwjers908fljsdf37459fsdfgdfwru=';
13
14  document.cookie = dummyCookie + '; domain=' + domain;
15  if (document.cookie.indexOf(dummyCookie) != -1) {
16    // Expire the dummy cookie if it is added successfully.
17    document.cookie = dummyCookie + '; Max-Age=0';
18    return true;
19  }
20  return false;
21}
22
23/**
24* Add the given cookie to the current web page.
25*
26* If path is not specified, default to '/'.
27* If domain is not specified, default to document.domain, otherwise remove its
28* port number.
29*
30* Validate name, value, domain and path of the cookie in the same way as the
31* method CanonicalCookie::Create in src/net/cookies/canonical_cookie.cc. Besides
32* the following requirements, name, value, domain and path of the cookie should
33* not start or end with ' ' or '\t', and should not contain '\n', '\r', or '\0'.
34* <ul>
35* <li>name: no ';' or '='
36* <li>value: no ';'
37* <li>path: starts with '/', no ';'
38* </ul>
39*
40* @param {!Object} cookie An object representing a Cookie JSON Object as
41*     specified in https://code.google.com/p/selenium/wiki/JsonWireProtocol.
42*/
43function addCookie(cookie) {
44  function isNameInvalid(value) {
45    return /(^[ \t])|([;=\n\r\0])|([ \t]$)/.test(value);
46  }
47  function isValueInvalid(value) {
48    return /(^[ \t])|([;\n\r\0])|([ \t]$)/.test(value);
49  }
50  function isPathInvalid(path) {
51    return path[0] != '/' || /([;\n\r\0])|([ \t]$)/.test(path);
52  }
53
54  var name = cookie['name'];
55  if (!name || isNameInvalid(name))
56    throw new Error('name of cookie is missing or invalid:"' + name + '"');
57
58  var value = cookie['value'] || '';
59  if (isValueInvalid(value))
60    throw new Error('value of cookie is invalid:"' + value + '"');
61
62  var domain = cookie['domain'];
63  // Remove the port number from domain.
64  if (domain) {
65    var domain_parts = domain.split(':');
66    if (domain_parts.length > 2)
67      throw new Error('domain of cookie has too many colons');
68    else if (domain_parts.length == 2)
69      domain = domain_parts[0];
70  }
71  // Validate domain.
72  if (domain && (isValueInvalid(domain) || !isDomainValid(domain))) {
73    var error = new Error();
74    error.code = 24;  // Error code for InvalidCookieDomain.
75    error.message = 'invalid domain:"' + domain + '"';
76    throw error;
77  }
78
79  var path = cookie['path'];
80  if (path && isPathInvalid(path))
81    throw new Error('path of cookie is invalid:"' + path + '"');
82
83  var newCookie = name + '=' + value;
84  newCookie += '; path=' + (path || '/');
85  if (domain)
86    newCookie += '; domain=' + domain;
87  if (cookie['expiry']) {
88    var expiredDate = new Date(cookie['expiry'] * 1000);
89    newCookie += '; expires=' + expiredDate.toUTCString();
90  }
91  if (cookie['secure'])
92    newCookie += '; secure';
93
94  document.cookie = newCookie;
95}
96