123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
- "use strict";
- const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
- Cu.import("resource://gre/modules/Log.jsm");
- Cu.import("chrome://marionette/content/error.js");
- const logger = Log.repository.getLogger("Marionette");
- this.EXPORTED_SYMBOLS = ["Cookies"];
- const IPV4_PORT_EXPR = /:\d+$/;
- /**
- * Interface for manipulating cookies from content space.
- */
- this.Cookies = class {
- /**
- * @param {function(): Document} documentFn
- * Closure that returns the current content document.
- * @param {Proxy(SyncChromeSender)} chromeProxy
- * A synchronous proxy interface to chrome space.
- */
- constructor(documentFn, chromeProxy) {
- this.documentFn_ = documentFn;
- this.chrome = chromeProxy;
- }
- get document() {
- return this.documentFn_();
- }
- [Symbol.iterator]() {
- let path = this.document.location.pathname || "/";
- let cs = this.chrome.getVisibleCookies(path, this.document.location.hostname)[0];
- return cs[Symbol.iterator]();
- }
- /**
- * Add a new cookie to a content document.
- *
- * @param {string} name
- * Cookie key.
- * @param {string} value
- * Cookie value.
- * @param {Object.<string, ?>} opts
- * An object with the optional fields {@code domain}, {@code path},
- * {@code secure}, {@code httpOnly}, and {@code expiry}.
- *
- * @return {Object.<string, ?>}
- * A serialisation of the cookie that was added.
- *
- * @throws UnableToSetCookieError
- * If the document's content type isn't HTML, the current document's
- * domain is a mismatch to the cookie's provided domain, or there
- * otherwise was issues with the input data.
- */
- add(name, value, opts={}) {
- if (typeof this.document == "undefined" || !this.document.contentType.match(/html/i)) {
- throw new UnableToSetCookieError(
- "You may only set cookies on HTML documents: " + this.document.contentType);
- }
- if (!opts.expiry) {
- // date twenty years into future, in seconds
- let date = new Date();
- let now = new Date(Date.now());
- date.setYear(now.getFullYear() + 20);
- opts.expiry = date.getTime() / 1000;
- }
- if (!opts.domain) {
- opts.domain = this.document.location.host;
- } else if (this.document.location.host.indexOf(opts.domain) < 0) {
- throw new InvalidCookieDomainError(
- "You may only set cookies for the current domain");
- }
- // remove port from domain, if present.
- // unfortunately this catches IPv6 addresses by mistake
- // TODO: Bug 814416
- opts.domain = opts.domain.replace(IPV4_PORT_EXPR, "");
- let cookie = {
- domain: opts.domain,
- path: opts.path,
- name: name,
- value: value,
- secure: opts.secure,
- httpOnly: opts.httpOnly,
- session: false,
- expiry: opts.expiry,
- };
- if (!this.chrome.addCookie(cookie)) {
- throw new UnableToSetCookieError();
- }
- return cookie;
- }
- /**
- * Delete cookie by reference or by name.
- *
- * @param {(string|Object.<string, ?>)} cookie
- * Name of cookie or cookie object.
- *
- * @throws {UnknownError}
- * If unable to delete the cookie.
- */
- delete(cookie) {
- let name;
- if (cookie.hasOwnProperty("name")) {
- name = cookie.name;
- } else {
- name = cookie;
- }
- for (let candidate of this) {
- if (candidate.name == name) {
- if (!this.chrome.deleteCookie(candidate)) {
- throw new UnknownError("Unable to delete cookie by name: " + name);
- }
- }
- }
- }
- };
|