PageRenderTime 65ms CodeModel.GetById 9ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 1ms

/extensions/cookie/test/unit/head_cookies.js

http://github.com/zpao/v8monkey
JavaScript | 571 lines | 467 code | 76 blank | 28 comment | 26 complexity | c594f38fa1e431560a4a9f26c1d93322 MD5 | raw file
  1/* Any copyright is dedicated to the Public Domain.
  2 * http://creativecommons.org/publicdomain/zero/1.0/
  3 */
  4
  5Components.utils.import("resource://gre/modules/Services.jsm");
  6Components.utils.import("resource://gre/modules/NetUtil.jsm");
  7Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
  8
  9const Cc = Components.classes;
 10const Ci = Components.interfaces;
 11const Cr = Components.results;
 12
 13XPCOMUtils.defineLazyServiceGetter(Services, "cookies",
 14                                   "@mozilla.org/cookieService;1",
 15                                   "nsICookieService");
 16XPCOMUtils.defineLazyServiceGetter(Services, "cookiemgr",
 17                                   "@mozilla.org/cookiemanager;1",
 18                                   "nsICookieManager2");
 19
 20XPCOMUtils.defineLazyServiceGetter(Services, "etld",
 21                                   "@mozilla.org/network/effective-tld-service;1",
 22                                   "nsIEffectiveTLDService");
 23
 24XPCOMUtils.defineLazyServiceGetter(Services, "permissions",
 25                                   "@mozilla.org/permissionmanager;1",
 26                                   "nsIPermissionManager");
 27
 28XPCOMUtils.defineLazyServiceGetter(Services, "pb",
 29                                   "@mozilla.org/privatebrowsing;1",
 30                                   "nsIPrivateBrowsingService");
 31
 32function do_check_throws(f, result, stack)
 33{
 34  if (!stack)
 35    stack = Components.stack.caller;
 36
 37  try {
 38    f();
 39  } catch (exc) {
 40    if (exc.result == result)
 41      return;
 42    do_throw("expected result " + result + ", caught " + exc, stack);
 43  }
 44  do_throw("expected result " + result + ", none thrown", stack);
 45}
 46
 47// Helper to step a generator function and catch a StopIteration exception.
 48function do_run_generator(generator)
 49{
 50  try {
 51    generator.next();
 52  } catch (e) {
 53    if (e != StopIteration)
 54      do_throw("caught exception " + e, Components.stack.caller);
 55  }
 56}
 57
 58// Helper to finish a generator function test.
 59function do_finish_generator_test(generator)
 60{
 61  do_execute_soon(function() {
 62    generator.close();
 63    do_test_finished();
 64  });
 65}
 66
 67function _observer(generator, topic) {
 68  Services.obs.addObserver(this, topic, false);
 69
 70  this.generator = generator;
 71  this.topic = topic;
 72}
 73
 74_observer.prototype = {
 75  observe: function (subject, topic, data) {
 76    do_check_eq(this.topic, topic);
 77
 78    Services.obs.removeObserver(this, this.topic);
 79
 80    // Continue executing the generator function.
 81    if (this.generator)
 82      do_run_generator(this.generator);
 83
 84    this.generator = null;
 85    this.topic = null;
 86  }
 87}
 88
 89// Close the cookie database. If a generator is supplied, it will be invoked
 90// once the close is complete.
 91function do_close_profile(generator, cleanse) {
 92  // Register an observer for db close.
 93  let obs = new _observer(generator, "cookie-db-closed");
 94
 95  // Close the db.
 96  let service = Services.cookies.QueryInterface(Ci.nsIObserver);
 97  service.observe(null, "profile-before-change", cleanse ? cleanse : "");
 98}
 99
100// Load the cookie database. If a generator is supplied, it will be invoked
101// once the load is complete.
102function do_load_profile(generator) {
103  // Register an observer for read completion.
104  let obs = new _observer(generator, "cookie-db-read");
105
106  // Load the profile.
107  let service = Services.cookies.QueryInterface(Ci.nsIObserver);
108  service.observe(null, "profile-do-change", "");
109}
110
111// Set four cookies; with & without channel, http and non-http; and test
112// the cookie count against 'expected' after each set.
113function do_set_cookies(uri, channel, session, expected) {
114  let suffix = session ? "" : "; max-age=1000";
115
116  // without channel
117  Services.cookies.setCookieString(uri, null, "oh=hai" + suffix, null);
118  do_check_eq(Services.cookiemgr.countCookiesFromHost(uri.host), expected[0]);
119  // with channel
120  Services.cookies.setCookieString(uri, null, "can=has" + suffix, channel);
121  do_check_eq(Services.cookiemgr.countCookiesFromHost(uri.host), expected[1]);
122  // without channel, from http
123  Services.cookies.setCookieStringFromHttp(uri, null, null, "cheez=burger" + suffix, null, null);
124  do_check_eq(Services.cookiemgr.countCookiesFromHost(uri.host), expected[2]);
125  // with channel, from http
126  Services.cookies.setCookieStringFromHttp(uri, null, null, "hot=dog" + suffix, null, channel);
127  do_check_eq(Services.cookiemgr.countCookiesFromHost(uri.host), expected[3]);
128}
129
130function do_count_enumerator(enumerator) {
131  let i = 0;
132  while (enumerator.hasMoreElements()) {
133    enumerator.getNext();
134    ++i;
135  }
136  return i;
137}
138
139function do_count_cookies() {
140  return do_count_enumerator(Services.cookiemgr.enumerator);
141}
142
143// Helper object to store cookie data.
144function Cookie(name,
145                value,
146                host,
147                path,
148                expiry,
149                lastAccessed,
150                creationTime,
151                isSession,
152                isSecure,
153                isHttpOnly)
154{
155  this.name = name;
156  this.value = value;
157  this.host = host;
158  this.path = path;
159  this.expiry = expiry;
160  this.lastAccessed = lastAccessed;
161  this.creationTime = creationTime;
162  this.isSession = isSession;
163  this.isSecure = isSecure;
164  this.isHttpOnly = isHttpOnly;
165
166  let strippedHost = host.charAt(0) == '.' ? host.slice(1) : host;
167
168  try {
169    this.baseDomain = Services.etld.getBaseDomainFromHost(strippedHost);
170  } catch (e) {
171    if (e.result == Cr.NS_ERROR_HOST_IS_IP_ADDRESS ||
172        e.result == Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS)
173      this.baseDomain = strippedHost;
174  }
175}
176
177// Object representing a database connection and associated statements. The
178// implementation varies depending on schema version.
179function CookieDatabaseConnection(file, schema)
180{
181  // Manually generate a cookies.sqlite file with appropriate rows, columns,
182  // and schema version. If it already exists, just set up our statements.
183  let exists = file.exists();
184
185  this.db = Services.storage.openDatabase(file);
186  this.schema = schema;
187  if (!exists)
188    this.db.schemaVersion = schema;
189
190  switch (schema) {
191  case 1:
192    {
193      if (!exists) {
194        this.db.executeSimpleSQL(
195          "CREATE TABLE moz_cookies (       \
196             id INTEGER PRIMARY KEY,        \
197             name TEXT,                     \
198             value TEXT,                    \
199             host TEXT,                     \
200             path TEXT,                     \
201             expiry INTEGER,                \
202             isSecure INTEGER,              \
203             isHttpOnly INTEGER)");
204      }
205
206      this.stmtInsert = this.db.createStatement(
207        "INSERT INTO moz_cookies (        \
208           id,                            \
209           name,                          \
210           value,                         \
211           host,                          \
212           path,                          \
213           expiry,                        \
214           isSecure,                      \
215           isHttpOnly)                    \
216           VALUES (                       \
217           :id,                           \
218           :name,                         \
219           :value,                        \
220           :host,                         \
221           :path,                         \
222           :expiry,                       \
223           :isSecure,                     \
224           :isHttpOnly)");
225
226      this.stmtDelete = this.db.createStatement(
227        "DELETE FROM moz_cookies WHERE id = :id");
228
229      break;
230    }
231
232  case 2:
233    {
234      if (!exists) {
235        this.db.executeSimpleSQL(
236          "CREATE TABLE moz_cookies (       \
237             id INTEGER PRIMARY KEY,        \
238             name TEXT,                     \
239             value TEXT,                    \
240             host TEXT,                     \
241             path TEXT,                     \
242             expiry INTEGER,                \
243             lastAccessed INTEGER,          \
244             isSecure INTEGER,              \
245             isHttpOnly INTEGER)");
246      }
247
248      this.stmtInsert = this.db.createStatement(
249        "INSERT OR REPLACE INTO moz_cookies ( \
250           id,                            \
251           name,                          \
252           value,                         \
253           host,                          \
254           path,                          \
255           expiry,                        \
256           lastAccessed,                  \
257           isSecure,                      \
258           isHttpOnly)                    \
259           VALUES (                       \
260           :id,                           \
261           :name,                         \
262           :value,                        \
263           :host,                         \
264           :path,                         \
265           :expiry,                       \
266           :lastAccessed,                 \
267           :isSecure,                     \
268           :isHttpOnly)");
269
270      this.stmtDelete = this.db.createStatement(
271        "DELETE FROM moz_cookies WHERE id = :id");
272
273      this.stmtUpdate = this.db.createStatement(
274        "UPDATE moz_cookies SET lastAccessed = :lastAccessed WHERE id = :id");
275
276      break;
277    }
278
279  case 3:
280    {
281      if (!exists) {
282        this.db.executeSimpleSQL(
283          "CREATE TABLE moz_cookies (       \
284            id INTEGER PRIMARY KEY,         \
285            baseDomain TEXT,                \
286            name TEXT,                      \
287            value TEXT,                     \
288            host TEXT,                      \
289            path TEXT,                      \
290            expiry INTEGER,                 \
291            lastAccessed INTEGER,           \
292            isSecure INTEGER,               \
293            isHttpOnly INTEGER)");
294
295        this.db.executeSimpleSQL(
296          "CREATE INDEX moz_basedomain ON moz_cookies (baseDomain)");
297      }
298
299      this.stmtInsert = this.db.createStatement(
300        "INSERT INTO moz_cookies (        \
301           id,                            \
302           baseDomain,                    \
303           name,                          \
304           value,                         \
305           host,                          \
306           path,                          \
307           expiry,                        \
308           lastAccessed,                  \
309           isSecure,                      \
310           isHttpOnly)                    \
311           VALUES (                       \
312           :id,                           \
313           :baseDomain,                   \
314           :name,                         \
315           :value,                        \
316           :host,                         \
317           :path,                         \
318           :expiry,                       \
319           :lastAccessed,                 \
320           :isSecure,                     \
321           :isHttpOnly)");
322
323      this.stmtDelete = this.db.createStatement(
324        "DELETE FROM moz_cookies WHERE id = :id");
325
326      this.stmtUpdate = this.db.createStatement(
327        "UPDATE moz_cookies SET lastAccessed = :lastAccessed WHERE id = :id");
328
329      break;
330    }
331
332  case 4:
333    {
334      if (!exists) {
335        this.db.executeSimpleSQL(
336          "CREATE TABLE moz_cookies (       \
337            id INTEGER PRIMARY KEY,         \
338            baseDomain TEXT,                \
339            name TEXT,                      \
340            value TEXT,                     \
341            host TEXT,                      \
342            path TEXT,                      \
343            expiry INTEGER,                 \
344            lastAccessed INTEGER,           \
345            creationTime INTEGER,           \
346            isSecure INTEGER,               \
347            isHttpOnly INTEGER              \
348            CONSTRAINT moz_uniqueid UNIQUE (name, host, path))");
349
350        this.db.executeSimpleSQL(
351          "CREATE INDEX moz_basedomain ON moz_cookies (baseDomain)");
352
353        this.db.executeSimpleSQL(
354          "PRAGMA journal_mode = WAL");
355      }
356
357      this.stmtInsert = this.db.createStatement(
358        "INSERT INTO moz_cookies (        \
359           baseDomain,                    \
360           name,                          \
361           value,                         \
362           host,                          \
363           path,                          \
364           expiry,                        \
365           lastAccessed,                  \
366           creationTime,                  \
367           isSecure,                      \
368           isHttpOnly)                    \
369           VALUES (                       \
370           :baseDomain,                   \
371           :name,                         \
372           :value,                        \
373           :host,                         \
374           :path,                         \
375           :expiry,                       \
376           :lastAccessed,                 \
377           :creationTime,                 \
378           :isSecure,                     \
379           :isHttpOnly)");
380
381      this.stmtDelete = this.db.createStatement(
382        "DELETE FROM moz_cookies          \
383           WHERE name = :name AND host = :host AND path = :path");
384
385      this.stmtUpdate = this.db.createStatement(
386        "UPDATE moz_cookies SET lastAccessed = :lastAccessed \
387           WHERE name = :name AND host = :host AND path = :path");
388
389      break;
390    }
391
392  default:
393    do_throw("unrecognized schemaVersion!");
394  }
395}
396
397CookieDatabaseConnection.prototype =
398{
399  insertCookie: function(cookie)
400  {
401    if (!(cookie instanceof Cookie))
402      do_throw("not a cookie");
403
404    switch (this.schema)
405    {
406    case 1:
407      this.stmtInsert.bindByName("id", cookie.creationTime);
408      this.stmtInsert.bindByName("name", cookie.name);
409      this.stmtInsert.bindByName("value", cookie.value);
410      this.stmtInsert.bindByName("host", cookie.host);
411      this.stmtInsert.bindByName("path", cookie.path);
412      this.stmtInsert.bindByName("expiry", cookie.expiry);
413      this.stmtInsert.bindByName("isSecure", cookie.isSecure);
414      this.stmtInsert.bindByName("isHttpOnly", cookie.isHttpOnly);
415      break;
416
417    case 2:
418      this.stmtInsert.bindByName("id", cookie.creationTime);
419      this.stmtInsert.bindByName("name", cookie.name);
420      this.stmtInsert.bindByName("value", cookie.value);
421      this.stmtInsert.bindByName("host", cookie.host);
422      this.stmtInsert.bindByName("path", cookie.path);
423      this.stmtInsert.bindByName("expiry", cookie.expiry);
424      this.stmtInsert.bindByName("lastAccessed", cookie.lastAccessed);
425      this.stmtInsert.bindByName("isSecure", cookie.isSecure);
426      this.stmtInsert.bindByName("isHttpOnly", cookie.isHttpOnly);
427      break;
428
429    case 3:
430      this.stmtInsert.bindByName("id", cookie.creationTime);
431      this.stmtInsert.bindByName("baseDomain", cookie.baseDomain);
432      this.stmtInsert.bindByName("name", cookie.name);
433      this.stmtInsert.bindByName("value", cookie.value);
434      this.stmtInsert.bindByName("host", cookie.host);
435      this.stmtInsert.bindByName("path", cookie.path);
436      this.stmtInsert.bindByName("expiry", cookie.expiry);
437      this.stmtInsert.bindByName("lastAccessed", cookie.lastAccessed);
438      this.stmtInsert.bindByName("isSecure", cookie.isSecure);
439      this.stmtInsert.bindByName("isHttpOnly", cookie.isHttpOnly);
440      break;
441
442    case 4:
443      this.stmtInsert.bindByName("baseDomain", cookie.baseDomain);
444      this.stmtInsert.bindByName("name", cookie.name);
445      this.stmtInsert.bindByName("value", cookie.value);
446      this.stmtInsert.bindByName("host", cookie.host);
447      this.stmtInsert.bindByName("path", cookie.path);
448      this.stmtInsert.bindByName("expiry", cookie.expiry);
449      this.stmtInsert.bindByName("lastAccessed", cookie.lastAccessed);
450      this.stmtInsert.bindByName("creationTime", cookie.creationTime);
451      this.stmtInsert.bindByName("isSecure", cookie.isSecure);
452      this.stmtInsert.bindByName("isHttpOnly", cookie.isHttpOnly);
453      break;
454
455    default:
456      do_throw("unrecognized schemaVersion!");
457    }
458
459    do_execute_stmt(this.stmtInsert);
460  },
461
462  deleteCookie: function(cookie)
463  {
464    if (!(cookie instanceof Cookie))
465      do_throw("not a cookie");
466
467    switch (this.db.schemaVersion)
468    {
469    case 1:
470    case 2:
471    case 3:
472      this.stmtDelete.bindByName("id", cookie.creationTime);
473      break;
474
475    case 4:
476      this.stmtDelete.bindByName("name", cookie.name);
477      this.stmtDelete.bindByName("host", cookie.host);
478      this.stmtDelete.bindByName("path", cookie.path);
479      break;
480
481    default:
482      do_throw("unrecognized schemaVersion!");
483    }
484
485    do_execute_stmt(this.stmtDelete);
486  },
487
488  updateCookie: function(cookie)
489  {
490    if (!(cookie instanceof Cookie))
491      do_throw("not a cookie");
492
493    switch (this.db.schemaVersion)
494    {
495    case 1:
496      do_throw("can't update a schema 1 cookie!");
497
498    case 2:
499    case 3:
500      this.stmtUpdate.bindByName("id", cookie.creationTime);
501      this.stmtUpdate.bindByName("lastAccessed", cookie.lastAccessed);
502      break;
503
504    case 4:
505      this.stmtDelete.bindByName("name", cookie.name);
506      this.stmtDelete.bindByName("host", cookie.host);
507      this.stmtDelete.bindByName("path", cookie.path);
508      this.stmtUpdate.bindByName("lastAccessed", cookie.lastAccessed);
509      break;
510
511    default:
512      do_throw("unrecognized schemaVersion!");
513    }
514
515    do_execute_stmt(this.stmtUpdate);
516  },
517
518  close: function()
519  {
520    this.stmtInsert.finalize();
521    this.stmtDelete.finalize();
522    if (this.stmtUpdate)
523      this.stmtUpdate.finalize();
524    this.db.close();
525
526    this.stmtInsert = null;
527    this.stmtDelete = null;
528    this.stmtUpdate = null;
529    this.db = null;
530  }
531}
532
533function do_get_cookie_file(profile)
534{
535  let file = profile.clone();
536  file.append("cookies.sqlite");
537  return file;
538}
539
540// Count the cookies from 'host' in a database. If 'host' is null, count all
541// cookies.
542function do_count_cookies_in_db(connection, host)
543{
544  let select = null;
545  if (host) {
546    select = connection.createStatement(
547      "SELECT COUNT(1) FROM moz_cookies WHERE host = :host");
548    select.bindByName("host", host);
549  } else {
550    select = connection.createStatement(
551      "SELECT COUNT(1) FROM moz_cookies");
552  }
553
554  select.executeStep();
555  let result = select.getInt32(0);
556  select.reset();
557  select.finalize();
558  return result;
559}
560
561// Execute 'stmt', ensuring that we reset it if it throws.
562function do_execute_stmt(stmt)
563{
564  try {
565    stmt.executeStep();
566    stmt.reset();
567  } catch (e) {
568    stmt.reset();
569    throw e;
570  }
571}