OnionLocationParent.sys.mjs (5258B)
1 // Copyright (c) 2020, The Tor Project, Inc. 2 3 import { TorStrings } from "resource://gre/modules/TorStrings.sys.mjs"; 4 5 // Prefs 6 7 // We keep the "prioritizeonions" name, even if obsolete, in order to 8 // prevent the notification from being shown again to upgrading users. 9 const NOTIFICATION_PREF = "privacy.prioritizeonions.showNotification"; 10 11 // Element IDs 12 const ONIONLOCATION_BOX_ID = "onion-location-box"; 13 const ONIONLOCATION_LABEL_ID = "onion-label"; 14 15 // Notification IDs 16 const NOTIFICATION_ID = "onion-location"; 17 const NOTIFICATION_ANCHOR_ID = "onion-location-box"; 18 19 // Strings 20 const STRING_ONION_AVAILABLE = TorStrings.onionLocation.onionAvailable; 21 const NOTIFICATION_CANCEL_LABEL = TorStrings.onionLocation.notNow; 22 const NOTIFICATION_CANCEL_ACCESSKEY = TorStrings.onionLocation.notNowAccessKey; 23 const NOTIFICATION_OK_LABEL = TorStrings.onionLocation.loadOnion; 24 const NOTIFICATION_OK_ACCESSKEY = TorStrings.onionLocation.loadOnionAccessKey; 25 const NOTIFICATION_TITLE = TorStrings.onionLocation.tryThis; 26 const NOTIFICATION_DESCRIPTION = TorStrings.onionLocation.description; 27 const NOTIFICATION_LEARN_MORE_URL = 28 TorStrings.onionLocation.learnMoreURLNotification; 29 30 /** 31 * This class contains the parent part of Onion Location. 32 */ 33 export class OnionLocationParent extends JSWindowActorParent { 34 // Listeners are added in BrowserGlue.jsm 35 receiveMessage(aMsg) { 36 switch (aMsg.name) { 37 case "OnionLocation:Set": { 38 let browser = this.browsingContext.embedderElement; 39 OnionLocationParent.setOnionLocation(browser); 40 break; 41 } 42 } 43 } 44 45 static init(document) { 46 document 47 .getElementById(ONIONLOCATION_BOX_ID) 48 .addEventListener("click", event => this.buttonClick(event)); 49 } 50 51 static buttonClick(event) { 52 if (event.button !== 0) { 53 return; 54 } 55 const win = event.target.ownerGlobal; 56 if (win.gBrowser) { 57 const browser = win.gBrowser.selectedBrowser; 58 OnionLocationParent.redirect(browser); 59 } 60 } 61 62 static redirect(browser) { 63 let windowGlobal = browser.browsingContext.currentWindowGlobal; 64 let actor = windowGlobal.getActor("OnionLocation"); 65 if (actor) { 66 actor.sendAsyncMessage("OnionLocation:Refresh", {}); 67 OnionLocationParent.setDisabled(browser); 68 } 69 } 70 71 static onStateChange(browser) { 72 delete browser._onionLocation; 73 OnionLocationParent.hideNotification(browser); 74 } 75 76 static setOnionLocation(browser) { 77 browser._onionLocation = true; 78 let tabBrowser = browser.getTabBrowser(); 79 if (tabBrowser && browser === tabBrowser.selectedBrowser) { 80 OnionLocationParent.updateOnionLocationBadge(browser); 81 } 82 } 83 84 static hideNotification(browser) { 85 const win = browser.ownerGlobal; 86 if (browser._onionLocationPrompt) { 87 win.PopupNotifications.remove(browser._onionLocationPrompt); 88 } 89 } 90 91 static showNotification(browser) { 92 const mustShow = Services.prefs.getBoolPref(NOTIFICATION_PREF, true); 93 if (!mustShow) { 94 return; 95 } 96 97 const win = browser.ownerGlobal; 98 Services.prefs.setBoolPref(NOTIFICATION_PREF, false); 99 100 const mainAction = { 101 label: NOTIFICATION_OK_LABEL, 102 accessKey: NOTIFICATION_OK_ACCESSKEY, 103 callback() { 104 OnionLocationParent.redirect(browser); 105 }, 106 }; 107 108 const cancelAction = { 109 label: NOTIFICATION_CANCEL_LABEL, 110 accessKey: NOTIFICATION_CANCEL_ACCESSKEY, 111 callback: () => {}, 112 }; 113 114 win.document.getElementById("onion-location-body-text").textContent = 115 NOTIFICATION_DESCRIPTION; 116 117 const options = { 118 autofocus: true, 119 persistent: true, 120 removeOnDismissal: false, 121 eventCallback(aTopic) { 122 if (aTopic === "removed") { 123 delete browser._onionLocationPrompt; 124 } 125 }, 126 learnMoreURL: NOTIFICATION_LEARN_MORE_URL, 127 hideClose: true, 128 popupOptions: { 129 position: "bottomright topright", 130 }, 131 }; 132 133 // A hacky way of setting the popup anchor outside the usual url bar icon 134 // box, similar to CRF and addons. 135 // See: https://searchfox.org/mozilla-esr115/rev/7962d6b7b17ee105ad64ab7906af2b9179f6e3d2/toolkit/modules/PopupNotifications.sys.mjs#46 136 browser[NOTIFICATION_ANCHOR_ID + "popupnotificationanchor"] = 137 win.document.getElementById(NOTIFICATION_ANCHOR_ID); 138 139 browser._onionLocationPrompt = win.PopupNotifications.show( 140 browser, 141 NOTIFICATION_ID, 142 NOTIFICATION_TITLE, 143 NOTIFICATION_ANCHOR_ID, 144 mainAction, 145 [cancelAction], 146 options 147 ); 148 } 149 150 static setEnabled(browser) { 151 const win = browser.ownerGlobal; 152 const label = win.document.getElementById(ONIONLOCATION_LABEL_ID); 153 label.textContent = STRING_ONION_AVAILABLE; 154 const elem = win.document.getElementById(ONIONLOCATION_BOX_ID); 155 elem.removeAttribute("hidden"); 156 } 157 158 static setDisabled(browser) { 159 const win = browser.ownerGlobal; 160 const elem = win.document.getElementById(ONIONLOCATION_BOX_ID); 161 elem.setAttribute("hidden", true); 162 } 163 164 static updateOnionLocationBadge(browser) { 165 if (browser._onionLocation) { 166 OnionLocationParent.setEnabled(browser); 167 OnionLocationParent.showNotification(browser); 168 } else { 169 OnionLocationParent.setDisabled(browser); 170 } 171 } 172 }