Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | "use strict"; |
michael@0 | 6 | |
michael@0 | 7 | module.metadata = { |
michael@0 | 8 | "stability": "unstable" |
michael@0 | 9 | }; |
michael@0 | 10 | |
michael@0 | 11 | const { Cc, Ci } = require("chrome"); |
michael@0 | 12 | const runtime = require("../system/runtime"); |
michael@0 | 13 | const { isString } = require("../lang/type"); |
michael@0 | 14 | const array = require("../util/array"); |
michael@0 | 15 | |
michael@0 | 16 | |
michael@0 | 17 | const SWP = "{{SEPARATOR}}"; |
michael@0 | 18 | const SEPARATOR = "-" |
michael@0 | 19 | const INVALID_COMBINATION = "Hotkey key combination must contain one or more " + |
michael@0 | 20 | "modifiers and only one key"; |
michael@0 | 21 | |
michael@0 | 22 | // Map of modifier key mappings. |
michael@0 | 23 | const MODIFIERS = exports.MODIFIERS = { |
michael@0 | 24 | 'accel': runtime.OS === "Darwin" ? 'meta' : 'control', |
michael@0 | 25 | 'meta': 'meta', |
michael@0 | 26 | 'control': 'control', |
michael@0 | 27 | 'ctrl': 'control', |
michael@0 | 28 | 'option': 'alt', |
michael@0 | 29 | 'command': 'meta', |
michael@0 | 30 | 'alt': 'alt', |
michael@0 | 31 | 'shift': 'shift' |
michael@0 | 32 | }; |
michael@0 | 33 | |
michael@0 | 34 | // Hash of key:code pairs for all the chars supported by `nsIDOMKeyEvent`. |
michael@0 | 35 | // This is just a copy of the `nsIDOMKeyEvent` hash with normalized names. |
michael@0 | 36 | // @See: http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/events/nsIDOMKeyEvent.idl |
michael@0 | 37 | const CODES = exports.CODES = new function Codes() { |
michael@0 | 38 | let nsIDOMKeyEvent = Ci.nsIDOMKeyEvent; |
michael@0 | 39 | // Names that will be substituted with a shorter analogs. |
michael@0 | 40 | let aliases = { |
michael@0 | 41 | 'subtract': '-', |
michael@0 | 42 | 'add': '+', |
michael@0 | 43 | 'equals': '=', |
michael@0 | 44 | 'slash': '/', |
michael@0 | 45 | 'backslash': '\\', |
michael@0 | 46 | 'openbracket': '[', |
michael@0 | 47 | 'closebracket': ']', |
michael@0 | 48 | 'quote': '\'', |
michael@0 | 49 | 'backquote': '`', |
michael@0 | 50 | 'period': '.', |
michael@0 | 51 | 'semicolon': ';', |
michael@0 | 52 | 'comma': ',' |
michael@0 | 53 | }; |
michael@0 | 54 | |
michael@0 | 55 | // Normalizing keys and copying values to `this` object. |
michael@0 | 56 | Object.keys(nsIDOMKeyEvent).filter(function(key) { |
michael@0 | 57 | // Filter out only key codes. |
michael@0 | 58 | return key.indexOf('DOM_VK') === 0; |
michael@0 | 59 | }).map(function(key) { |
michael@0 | 60 | // Map to key:values |
michael@0 | 61 | return [ key, nsIDOMKeyEvent[key] ]; |
michael@0 | 62 | }).map(function([key, value]) { |
michael@0 | 63 | return [ key.replace('DOM_VK_', '').replace('_', '').toLowerCase(), value ]; |
michael@0 | 64 | }).forEach(function ([ key, value ]) { |
michael@0 | 65 | this[aliases[key] || key] = value; |
michael@0 | 66 | }, this); |
michael@0 | 67 | }; |
michael@0 | 68 | |
michael@0 | 69 | // Inverted `CODES` hash of `code:key`. |
michael@0 | 70 | const KEYS = exports.KEYS = new function Keys() { |
michael@0 | 71 | Object.keys(CODES).forEach(function(key) { |
michael@0 | 72 | this[CODES[key]] = key; |
michael@0 | 73 | }, this) |
michael@0 | 74 | } |
michael@0 | 75 | |
michael@0 | 76 | exports.getKeyForCode = function getKeyForCode(code) { |
michael@0 | 77 | return (code in KEYS) && KEYS[code]; |
michael@0 | 78 | }; |
michael@0 | 79 | exports.getCodeForKey = function getCodeForKey(key) { |
michael@0 | 80 | return (key in CODES) && CODES[key]; |
michael@0 | 81 | }; |
michael@0 | 82 | |
michael@0 | 83 | /** |
michael@0 | 84 | * Utility function that takes string or JSON that defines a `hotkey` and |
michael@0 | 85 | * returns normalized string version of it. |
michael@0 | 86 | * @param {JSON|String} hotkey |
michael@0 | 87 | * @param {String} [separator=" "] |
michael@0 | 88 | * Optional string that represents separator used to concatenate keys in the |
michael@0 | 89 | * given `hotkey`. |
michael@0 | 90 | * @returns {String} |
michael@0 | 91 | * @examples |
michael@0 | 92 | * |
michael@0 | 93 | * require("keyboard/hotkeys").normalize("b Shift accel"); |
michael@0 | 94 | * // 'control shift b' -> on windows & linux |
michael@0 | 95 | * // 'meta shift b' -> on mac |
michael@0 | 96 | * require("keyboard/hotkeys").normalize("alt-d-shift", "-"); |
michael@0 | 97 | * // 'alt shift d' |
michael@0 | 98 | */ |
michael@0 | 99 | var normalize = exports.normalize = function normalize(hotkey, separator) { |
michael@0 | 100 | if (!isString(hotkey)) |
michael@0 | 101 | hotkey = toString(hotkey, separator); |
michael@0 | 102 | return toString(toJSON(hotkey, separator), separator); |
michael@0 | 103 | }; |
michael@0 | 104 | |
michael@0 | 105 | /* |
michael@0 | 106 | * Utility function that splits a string of characters that defines a `hotkey` |
michael@0 | 107 | * into modifier keys and the defining key. |
michael@0 | 108 | * @param {String} hotkey |
michael@0 | 109 | * @param {String} [separator=" "] |
michael@0 | 110 | * Optional string that represents separator used to concatenate keys in the |
michael@0 | 111 | * given `hotkey`. |
michael@0 | 112 | * @returns {JSON} |
michael@0 | 113 | * @examples |
michael@0 | 114 | * |
michael@0 | 115 | * require("keyboard/hotkeys").toJSON("accel shift b"); |
michael@0 | 116 | * // { key: 'b', modifiers: [ 'control', 'shift' ] } -> on windows & linux |
michael@0 | 117 | * // { key: 'b', modifiers: [ 'meta', 'shift' ] } -> on mac |
michael@0 | 118 | * |
michael@0 | 119 | * require("keyboard/hotkeys").normalize("alt-d-shift", "-"); |
michael@0 | 120 | * // { key: 'd', modifiers: [ 'alt', 'shift' ] } |
michael@0 | 121 | */ |
michael@0 | 122 | var toJSON = exports.toJSON = function toJSON(hotkey, separator) { |
michael@0 | 123 | separator = separator || SEPARATOR; |
michael@0 | 124 | // Since default separator is `-`, combination may take form of `alt--`. To |
michael@0 | 125 | // avoid misbehavior we replace `--` with `-{{SEPARATOR}}` where |
michael@0 | 126 | // `{{SEPARATOR}}` can be swapped later. |
michael@0 | 127 | hotkey = hotkey.toLowerCase().replace(separator + separator, separator + SWP); |
michael@0 | 128 | |
michael@0 | 129 | let value = {}; |
michael@0 | 130 | let modifiers = []; |
michael@0 | 131 | let keys = hotkey.split(separator); |
michael@0 | 132 | keys.forEach(function(name) { |
michael@0 | 133 | // If name is `SEPARATOR` than we swap it back. |
michael@0 | 134 | if (name === SWP) |
michael@0 | 135 | name = separator; |
michael@0 | 136 | if (name in MODIFIERS) { |
michael@0 | 137 | array.add(modifiers, MODIFIERS[name]); |
michael@0 | 138 | } else { |
michael@0 | 139 | if (!value.key) |
michael@0 | 140 | value.key = name; |
michael@0 | 141 | else |
michael@0 | 142 | throw new TypeError(INVALID_COMBINATION); |
michael@0 | 143 | } |
michael@0 | 144 | }); |
michael@0 | 145 | |
michael@0 | 146 | if (!value.key) |
michael@0 | 147 | throw new TypeError(INVALID_COMBINATION); |
michael@0 | 148 | |
michael@0 | 149 | value.modifiers = modifiers.sort(); |
michael@0 | 150 | return value; |
michael@0 | 151 | }; |
michael@0 | 152 | |
michael@0 | 153 | /** |
michael@0 | 154 | * Utility function that takes object that defines a `hotkey` and returns |
michael@0 | 155 | * string representation of it. |
michael@0 | 156 | * |
michael@0 | 157 | * _Please note that this function does not validates data neither it normalizes |
michael@0 | 158 | * it, if you are unsure that data is well formed use `normalize` function |
michael@0 | 159 | * instead. |
michael@0 | 160 | * |
michael@0 | 161 | * @param {JSON} hotkey |
michael@0 | 162 | * @param {String} [separator=" "] |
michael@0 | 163 | * Optional string that represents separator used to concatenate keys in the |
michael@0 | 164 | * given `hotkey`. |
michael@0 | 165 | * @returns {String} |
michael@0 | 166 | * @examples |
michael@0 | 167 | * |
michael@0 | 168 | * require("keyboard/hotkeys").toString({ |
michael@0 | 169 | * key: 'b', |
michael@0 | 170 | * modifiers: [ 'control', 'shift' ] |
michael@0 | 171 | * }, '+'); |
michael@0 | 172 | * // 'control+shift+b |
michael@0 | 173 | * |
michael@0 | 174 | */ |
michael@0 | 175 | var toString = exports.toString = function toString(hotkey, separator) { |
michael@0 | 176 | let keys = hotkey.modifiers.slice(); |
michael@0 | 177 | keys.push(hotkey.key); |
michael@0 | 178 | return keys.join(separator || SEPARATOR); |
michael@0 | 179 | }; |
michael@0 | 180 | |
michael@0 | 181 | /** |
michael@0 | 182 | * Utility function takes `key` name and returns `true` if it's function key |
michael@0 | 183 | * (F1, ..., F24) and `false` if it's not. |
michael@0 | 184 | */ |
michael@0 | 185 | var isFunctionKey = exports.isFunctionKey = function isFunctionKey(key) { |
michael@0 | 186 | var $ |
michael@0 | 187 | return key[0].toLowerCase() === 'f' && |
michael@0 | 188 | ($ = parseInt(key.substr(1)), 0 < $ && $ < 25); |
michael@0 | 189 | }; |