summaryrefslogtreecommitdiffstats
path: root/devtools/shared/gcli/commands/cookie.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/shared/gcli/commands/cookie.js')
-rw-r--r--devtools/shared/gcli/commands/cookie.js300
1 files changed, 300 insertions, 0 deletions
diff --git a/devtools/shared/gcli/commands/cookie.js b/devtools/shared/gcli/commands/cookie.js
new file mode 100644
index 000000000..f1680042f
--- /dev/null
+++ b/devtools/shared/gcli/commands/cookie.js
@@ -0,0 +1,300 @@
+/* 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";
+
+/**
+ * XXX: bug 1221488 is required to make these commands run on the server.
+ * If we want these commands to run on remote devices/connections, they need to
+ * run on the server (runAt=server). Unfortunately, cookie commands not only
+ * need to run on the server, they also need to access to the parent process to
+ * retrieve and manipulate cookies via nsICookieManager2.
+ * However, server-running commands have no way of accessing the parent process
+ * for now.
+ *
+ * So, because these cookie commands, as of today, only run in the developer
+ * toolbar (the gcli command bar), and because this toolbar is only available on
+ * a local Firefox desktop tab (not in webide or the browser toolbox), we can
+ * make the commands run on the client.
+ * This way, they'll always run in the parent process.
+ */
+
+const { Ci, Cc } = require("chrome");
+const l10n = require("gcli/l10n");
+const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "cookieMgr", function() {
+ return Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
+});
+
+/**
+ * Check host value and remove port part as it is not used
+ * for storing cookies.
+ *
+ * Parameter will usually be `new URL(context.environment.target.url).host`
+ */
+function sanitizeHost(host) {
+ if (host == null || host == "") {
+ throw new Error(l10n.lookup("cookieListOutNonePage"));
+ }
+ return host.split(":")[0];
+}
+
+/**
+ * The cookie 'expires' value needs converting into something more readable.
+ *
+ * And the unit of expires is sec, the unit that in argument of Date() needs
+ * millisecond.
+ */
+function translateExpires(expires) {
+ if (expires == 0) {
+ return l10n.lookup("cookieListOutSession");
+ }
+
+ let expires_msec = expires * 1000;
+
+ return (new Date(expires_msec)).toLocaleString();
+}
+
+/**
+ * Check if a given cookie matches a given host
+ */
+function isCookieAtHost(cookie, host) {
+ if (cookie.host == null) {
+ return host == null;
+ }
+ if (cookie.host.startsWith(".")) {
+ return ("." + host).endsWith(cookie.host);
+ }
+ if (cookie.host === "") {
+ return host.startsWith("file://" + cookie.path);
+ }
+ return cookie.host == host;
+}
+
+exports.items = [
+ {
+ name: "cookie",
+ description: l10n.lookup("cookieDesc"),
+ manual: l10n.lookup("cookieManual")
+ },
+ {
+ item: "command",
+ runAt: "client",
+ name: "cookie list",
+ description: l10n.lookup("cookieListDesc"),
+ manual: l10n.lookup("cookieListManual"),
+ returnType: "cookies",
+ exec: function(args, context) {
+ if (context.environment.target.isRemote) {
+ throw new Error("The cookie gcli commands only work in a local tab, " +
+ "see bug 1221488");
+ }
+ let host = new URL(context.environment.target.url).host;
+ let contentWindow = context.environment.window;
+ host = sanitizeHost(host);
+ let enm = cookieMgr.getCookiesFromHost(host, contentWindow.document.
+ nodePrincipal.
+ originAttributes);
+
+ let cookies = [];
+ while (enm.hasMoreElements()) {
+ let cookie = enm.getNext().QueryInterface(Ci.nsICookie);
+ if (isCookieAtHost(cookie, host)) {
+ cookies.push({
+ host: cookie.host,
+ name: cookie.name,
+ value: cookie.value,
+ path: cookie.path,
+ expires: cookie.expires,
+ secure: cookie.secure,
+ httpOnly: cookie.httpOnly,
+ sameDomain: cookie.sameDomain
+ });
+ }
+ }
+
+ return cookies;
+ }
+ },
+ {
+ item: "command",
+ runAt: "client",
+ name: "cookie remove",
+ description: l10n.lookup("cookieRemoveDesc"),
+ manual: l10n.lookup("cookieRemoveManual"),
+ params: [
+ {
+ name: "name",
+ type: "string",
+ description: l10n.lookup("cookieRemoveKeyDesc"),
+ }
+ ],
+ exec: function(args, context) {
+ if (context.environment.target.isRemote) {
+ throw new Error("The cookie gcli commands only work in a local tab, " +
+ "see bug 1221488");
+ }
+ let host = new URL(context.environment.target.url).host;
+ let contentWindow = context.environment.window;
+ host = sanitizeHost(host);
+ let enm = cookieMgr.getCookiesFromHost(host, contentWindow.document.
+ nodePrincipal.
+ originAttributes);
+
+ while (enm.hasMoreElements()) {
+ let cookie = enm.getNext().QueryInterface(Ci.nsICookie);
+ if (isCookieAtHost(cookie, host)) {
+ if (cookie.name == args.name) {
+ cookieMgr.remove(cookie.host, cookie.name, cookie.path,
+ false, cookie.originAttributes);
+ }
+ }
+ }
+ }
+ },
+ {
+ item: "converter",
+ from: "cookies",
+ to: "view",
+ exec: function(cookies, context) {
+ if (cookies.length == 0) {
+ let host = new URL(context.environment.target.url).host;
+ host = sanitizeHost(host);
+ let msg = l10n.lookupFormat("cookieListOutNoneHost", [ host ]);
+ return context.createView({ html: "<span>" + msg + "</span>" });
+ }
+
+ for (let cookie of cookies) {
+ cookie.expires = translateExpires(cookie.expires);
+
+ let noAttrs = !cookie.secure && !cookie.httpOnly && !cookie.sameDomain;
+ cookie.attrs = (cookie.secure ? "secure" : " ") +
+ (cookie.httpOnly ? "httpOnly" : " ") +
+ (cookie.sameDomain ? "sameDomain" : " ") +
+ (noAttrs ? l10n.lookup("cookieListOutNone") : " ");
+ }
+
+ return context.createView({
+ html:
+ "<ul class='gcli-cookielist-list'>" +
+ " <li foreach='cookie in ${cookies}'>" +
+ " <div>${cookie.name}=${cookie.value}</div>" +
+ " <table class='gcli-cookielist-detail'>" +
+ " <tr>" +
+ " <td>" + l10n.lookup("cookieListOutHost") + "</td>" +
+ " <td>${cookie.host}</td>" +
+ " </tr>" +
+ " <tr>" +
+ " <td>" + l10n.lookup("cookieListOutPath") + "</td>" +
+ " <td>${cookie.path}</td>" +
+ " </tr>" +
+ " <tr>" +
+ " <td>" + l10n.lookup("cookieListOutExpires") + "</td>" +
+ " <td>${cookie.expires}</td>" +
+ " </tr>" +
+ " <tr>" +
+ " <td>" + l10n.lookup("cookieListOutAttributes") + "</td>" +
+ " <td>${cookie.attrs}</td>" +
+ " </tr>" +
+ " <tr><td colspan='2'>" +
+ " <span class='gcli-out-shortcut' onclick='${onclick}'" +
+ " data-command='cookie set ${cookie.name} '" +
+ " >" + l10n.lookup("cookieListOutEdit") + "</span>" +
+ " <span class='gcli-out-shortcut'" +
+ " onclick='${onclick}' ondblclick='${ondblclick}'" +
+ " data-command='cookie remove ${cookie.name}'" +
+ " >" + l10n.lookup("cookieListOutRemove") + "</span>" +
+ " </td></tr>" +
+ " </table>" +
+ " </li>" +
+ "</ul>",
+ data: {
+ options: { allowEval: true },
+ cookies: cookies,
+ onclick: context.update,
+ ondblclick: context.updateExec
+ }
+ });
+ }
+ },
+ {
+ item: "command",
+ runAt: "client",
+ name: "cookie set",
+ description: l10n.lookup("cookieSetDesc"),
+ manual: l10n.lookup("cookieSetManual"),
+ params: [
+ {
+ name: "name",
+ type: "string",
+ description: l10n.lookup("cookieSetKeyDesc")
+ },
+ {
+ name: "value",
+ type: "string",
+ description: l10n.lookup("cookieSetValueDesc")
+ },
+ {
+ group: l10n.lookup("cookieSetOptionsDesc"),
+ params: [
+ {
+ name: "path",
+ type: { name: "string", allowBlank: true },
+ defaultValue: "/",
+ description: l10n.lookup("cookieSetPathDesc")
+ },
+ {
+ name: "domain",
+ type: "string",
+ defaultValue: null,
+ description: l10n.lookup("cookieSetDomainDesc")
+ },
+ {
+ name: "secure",
+ type: "boolean",
+ description: l10n.lookup("cookieSetSecureDesc")
+ },
+ {
+ name: "httpOnly",
+ type: "boolean",
+ description: l10n.lookup("cookieSetHttpOnlyDesc")
+ },
+ {
+ name: "session",
+ type: "boolean",
+ description: l10n.lookup("cookieSetSessionDesc")
+ },
+ {
+ name: "expires",
+ type: "string",
+ defaultValue: "Jan 17, 2038",
+ description: l10n.lookup("cookieSetExpiresDesc")
+ },
+ ]
+ }
+ ],
+ exec: function(args, context) {
+ if (context.environment.target.isRemote) {
+ throw new Error("The cookie gcli commands only work in a local tab, " +
+ "see bug 1221488");
+ }
+ let host = new URL(context.environment.target.url).host;
+ host = sanitizeHost(host);
+ let time = Date.parse(args.expires) / 1000;
+ let contentWindow = context.environment.window;
+ cookieMgr.add(args.domain ? "." + args.domain : host,
+ args.path ? args.path : "/",
+ args.name,
+ args.value,
+ args.secure,
+ args.httpOnly,
+ args.session,
+ time,
+ contentWindow.document.
+ nodePrincipal.
+ originAttributes);
+ }
+ }
+];