|
| 1 | +const CC = Components.classes; |
| 2 | +const CI = Components.interfaces; |
| 3 | +const CU = Components.utils; |
| 4 | + |
| 5 | +var HTTPSEverywhere = CC["@eff.org/https-everywhere;1"] |
| 6 | + .getService(CI.nsISupports).wrappedJSObject; |
| 7 | + |
| 8 | +CU.import("resource://gre/modules/Prompt.jsm"); |
| 9 | + |
| 10 | +var menuId; |
| 11 | +var urlbarId; |
| 12 | +var aWindow = getWindow(); |
| 13 | + |
| 14 | + |
| 15 | +/* |
| 16 | + * Setup/Teardown for the UI |
| 17 | + */ |
| 18 | + |
| 19 | +function loadIntoWindow() { |
| 20 | + if (!aWindow) { |
| 21 | + return; |
| 22 | + } |
| 23 | + var enabled = HTTPSEverywhere.prefs.getBoolPref("globalEnabled"); |
| 24 | + addToggleItemToMenu(enabled); |
| 25 | + if (enabled) { |
| 26 | + urlbarId = aWindow.NativeWindow.pageactions.add(urlbarOptions); |
| 27 | + } else if (urlbarId) { |
| 28 | + aWindow.NativeWindow.pageactions.remove(urlbarId); |
| 29 | + } |
| 30 | +} |
| 31 | + |
| 32 | +function unloadFromWindow() { |
| 33 | + if (!aWindow) { |
| 34 | + return; |
| 35 | + } |
| 36 | + aWindow.NativeWindow.menu.remove(menuId); |
| 37 | + aWindow.NativeWindow.pageactions.remove(urlbarId); |
| 38 | +} |
| 39 | + |
| 40 | + |
| 41 | +/* |
| 42 | + * Add a menu item to toggle HTTPS Everywhere |
| 43 | + */ |
| 44 | + |
| 45 | +function addToggleItemToMenu(enabled) { |
| 46 | + if (menuId) { aWindow.NativeWindow.menu.remove(menuId); } |
| 47 | + var menuLabel = enabled ? "HTTPS Everywhere on" : "HTTPS Everywhere off"; |
| 48 | + menuId = aWindow.NativeWindow.menu.add(menuLabel, null, function() { |
| 49 | + popupToggleMenu(aWindow, enabled); |
| 50 | + }); |
| 51 | +} |
| 52 | + |
| 53 | +function popupToggleMenu(aWindow, enabled) { |
| 54 | + var buttons = [ |
| 55 | + { |
| 56 | + label: "Yes", |
| 57 | + callback: function() { |
| 58 | + toggleEnabledState(); |
| 59 | + var msg = enabled ? "HTTPS Everywhere disabled!" : "HTTPS Everywhere enabled!"; |
| 60 | + aWindow.NativeWindow.toast.show(msg, "short"); |
| 61 | + return true; |
| 62 | + } |
| 63 | + }, { |
| 64 | + label: "No", |
| 65 | + callback: function() { return false; } |
| 66 | + } |
| 67 | + ]; |
| 68 | + var newState = enabled ? "off?" : "on?"; |
| 69 | + aWindow.NativeWindow.doorhanger.show("Would you like to turn HTTPS Everywhere "+newState, |
| 70 | + "doorhanger-toggle", buttons); |
| 71 | +} |
| 72 | + |
| 73 | + |
| 74 | +/* |
| 75 | + * The HTTPS Everywhere icon in the URL bar shows a popup of rules that the |
| 76 | + * user can activate/deactivate. On long click, reset all rules to defaults. |
| 77 | + */ |
| 78 | + |
| 79 | +var popupInfo = { |
| 80 | + rules: [], |
| 81 | + ruleItems: [], |
| 82 | + ruleStatus: [], |
| 83 | + alist: null, |
| 84 | + getApplicableList: function() { |
| 85 | + var browser = aWindow.BrowserApp.selectedBrowser; |
| 86 | + return HTTPSEverywhere.getApplicableListForBrowser(browser); |
| 87 | + }, |
| 88 | + fill: function() { |
| 89 | + this.clear(); |
| 90 | + this.alist = this.getApplicableList(); |
| 91 | + HTTPSEverywhere.log(4,"applicable list active: "+JSON.stringify(this.alist.active)); |
| 92 | + HTTPSEverywhere.log(4,"applicable list inactive: "+JSON.stringify(this.alist.inactive)); |
| 93 | + for (var rule in this.alist.all) { |
| 94 | + if (this.alist.active.hasOwnProperty(rule)) { |
| 95 | + // active rules are checked and toggleable |
| 96 | + this.ruleItems.push({ label: rule, selected: true }); |
| 97 | + this.ruleStatus.push(true); |
| 98 | + this.rules.push(this.alist.active[rule]); |
| 99 | + } else if (this.alist.moot.hasOwnProperty(rule)) { |
| 100 | + // moot rules are checked and toggleable too |
| 101 | + this.ruleItems.push({ label: rule, selected: true }); |
| 102 | + this.ruleStatus.push(true); |
| 103 | + this.rules.push(this.alist.moot[rule]); |
| 104 | + } else if (this.alist.inactive.hasOwnProperty(rule)) { |
| 105 | + // inactive rules are unchecked and toggleable |
| 106 | + this.ruleItems.push({ label: rule }); |
| 107 | + this.ruleStatus.push(false); |
| 108 | + this.rules.push(this.alist.inactive[rule]); |
| 109 | + } else if (this.alist.breaking.hasOwnProperty(rule)) { |
| 110 | + // breaking rules are get a unicode clockwise arrow next to them |
| 111 | + var ruleLabel = "\u21B7"+rule; |
| 112 | + var isSelected = this.alist.breaking[rule].active; |
| 113 | + this.ruleItems.push({ label: ruleLabel, selected: isSelected }); |
| 114 | + this.ruleStatus.push(isSelected); |
| 115 | + this.rules.push(this.alist.breaking[rule]); |
| 116 | + } |
| 117 | + } |
| 118 | + }, |
| 119 | + clear: function() { |
| 120 | + this.rules = []; |
| 121 | + this.ruleItems = []; |
| 122 | + this.ruleStatus = []; |
| 123 | + this.alist = {}; |
| 124 | + } |
| 125 | +}; |
| 126 | + |
| 127 | +var urlbarOptions = { |
| 128 | + |
| 129 | + title: "HTTPS Everywhere", |
| 130 | + |
| 131 | + icon: "chrome://https-everywhere/skin/https-everywhere-128.png", |
| 132 | + |
| 133 | + clickCallback: function() { |
| 134 | + popupInfo.fill(); |
| 135 | + rulesPrompt.setMultiChoiceItems(popupInfo.ruleItems); |
| 136 | + rulesPrompt.show(function(data) { |
| 137 | + var db = data.button; |
| 138 | + if (db === -1) { return null; } // user didn't click the accept button |
| 139 | + if (popupInfo.rules.length !== db.length) { |
| 140 | + // Why does db sometimes have an extra entry that doesn't correspond |
| 141 | + // to any of the ruleItems? No idea, but let's log it. |
| 142 | + HTTPSEverywhere.log(5,"Got length mismatch between popupInfo.ruleItems and data.button"); |
| 143 | + HTTPSEverywhere.log(4,"Applicable rules: "+JSON.stringify(popupInfo.rules)); |
| 144 | + HTTPSEverywhere.log(4, "data.button: "+JSON.stringify(db)); |
| 145 | + } |
| 146 | + for (var i=0; i<popupInfo.rules.length; i++) { |
| 147 | + if (popupInfo.ruleStatus[i] !== db[i]) { |
| 148 | + HTTPSEverywhere.log(4, "toggling: "+JSON.stringify(popupInfo.rules[i])); |
| 149 | + popupInfo.rules[i].toggle(); |
| 150 | + } |
| 151 | + } |
| 152 | + reloadTab(); |
| 153 | + return null; |
| 154 | + }); |
| 155 | + }, |
| 156 | + |
| 157 | + longClickCallback: function() { popupResetDefaultsMenu(aWindow); } |
| 158 | +}; |
| 159 | + |
| 160 | +var rulesPrompt = new Prompt({ |
| 161 | + window: aWindow, |
| 162 | + title: "Enable/disable rules", |
| 163 | + buttons: ["Apply changes"] |
| 164 | +}); |
| 165 | + |
| 166 | +function popupResetDefaultsMenu(aWindow) { |
| 167 | + var buttons = [ |
| 168 | + { |
| 169 | + label: "Yes", |
| 170 | + callback: function() { |
| 171 | + resetToDefaults(); |
| 172 | + var msg = "Default rules reset."; |
| 173 | + aWindow.NativeWindow.toast.show(msg, "short"); |
| 174 | + return true; |
| 175 | + } |
| 176 | + }, { |
| 177 | + label: "No", |
| 178 | + callback: function() { return false; } |
| 179 | + } |
| 180 | + ]; |
| 181 | + aWindow.NativeWindow.doorhanger.show("Reset all HTTPS Everywhere rules to defaults?", |
| 182 | + "doorhanger-reset", buttons); |
| 183 | +} |
| 184 | + |
| 185 | + |
| 186 | +/* |
| 187 | + * Some useful utils |
| 188 | + */ |
| 189 | + |
| 190 | +function reloadTab() { |
| 191 | + // There seems to be no API to do this directly? |
| 192 | + aWindow.BrowserApp.selectedTab.window.location.reload(); |
| 193 | +} |
| 194 | + |
| 195 | +function toggleEnabledState(){ |
| 196 | + HTTPSEverywhere.toggleEnabledState(); |
| 197 | + loadIntoWindow(); |
| 198 | + reloadTab(); |
| 199 | +} |
| 200 | + |
| 201 | +function resetToDefaults() { |
| 202 | + HTTPSEverywhere.https_rules.resetRulesetsToDefaults(); |
| 203 | + reloadTab(); |
| 204 | +} |
| 205 | + |
| 206 | +function getWindow() { |
| 207 | + return CC['@mozilla.org/appshell/window-mediator;1'] |
| 208 | + .getService(CI.nsIWindowMediator) |
| 209 | + .getMostRecentWindow('navigator:browser'); |
| 210 | +} |
| 211 | + |
| 212 | + |
| 213 | +/* |
| 214 | + * Here's the external API to this UI module |
| 215 | + */ |
| 216 | + |
| 217 | +var AndroidUI = { |
| 218 | + init: function() { |
| 219 | + loadIntoWindow(); |
| 220 | + }, |
| 221 | + shutdown: function() { |
| 222 | + unloadFromWindow(); |
| 223 | + } |
| 224 | +}; |
| 225 | + |
| 226 | +var EXPORTED_SYMBOLS = ["AndroidUI"]; |
0 commit comments