diff options
Diffstat (limited to '')
-rw-r--r-- | comm/mail/components/im/content/am-im.js | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/comm/mail/components/im/content/am-im.js b/comm/mail/components/im/content/am-im.js new file mode 100644 index 0000000000..494e0aa1fd --- /dev/null +++ b/comm/mail/components/im/content/am-im.js @@ -0,0 +1,291 @@ +/* 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/. */ + +// chat/content/imAccountOptionsHelper.js +/* globals accountOptionsHelper */ + +const { ChatIcons } = ChromeUtils.importESModule( + "resource:///modules/chatIcons.sys.mjs" +); +ChromeUtils.defineESModuleGetters(this, { + ChatEncryption: "resource:///modules/ChatEncryption.sys.mjs", + OTR: "resource:///modules/OTR.sys.mjs", + OTRUI: "resource:///modules/OTRUI.sys.mjs", +}); + +var autoJoinPref = "autoJoin"; + +function onPreInit(aAccount, aAccountValue) { + account.init(aAccount.incomingServer.wrappedJSObject.imAccount); +} + +function onBeforeUnload() { + if (account.encryptionObserver) { + Services.obs.removeObserver( + account.encryptionObserver, + "account-sessions-changed" + ); + Services.obs.removeObserver( + account.encryptionObserver, + "account-encryption-status-changed" + ); + } +} + +var account = { + async init(aAccount) { + let title = document.querySelector(".dialogheader .dialogheader-title"); + let defaultTitle = title.getAttribute("defaultTitle"); + let titleValue; + + if (aAccount.name) { + titleValue = defaultTitle + " - <" + aAccount.name + ">"; + } else { + titleValue = defaultTitle; + } + + title.setAttribute("value", titleValue); + document.title = titleValue; + + this.account = aAccount; + this.proto = this.account.protocol; + document.getElementById("accountName").value = this.account.name; + document.getElementById("protocolName").value = + this.proto.name || this.proto.id; + document.getElementById("protocolIcon").src = ChatIcons.getProtocolIconURI( + this.proto, + 48 + ); + + let password = document.getElementById("server.password"); + let passwordBox = document.getElementById("passwordBox"); + if (this.proto.noPassword) { + passwordBox.hidden = true; + password.removeAttribute("wsm_persist"); + } else { + passwordBox.hidden = false; + try { + // Should we force layout here to ensure password.value works? + // Will throw if we don't have a protocol plugin for the account. + password.value = this.account.password; + password.setAttribute("wsm_persist", "true"); + } catch (e) { + passwordBox.hidden = true; + password.removeAttribute("wsm_persist"); + } + } + + document.getElementById("server.alias").value = this.account.alias; + + if (ChatEncryption.canConfigureEncryption(this.account.protocol)) { + document.getElementById("imTabEncryption").hidden = false; + document.querySelector(".otr-settings").hidden = !OTRUI.enabled; + document.getElementById("server.otrAllowMsgLog").value = + this.account.otrAllowMsgLog; + if (OTRUI.enabled) { + document.getElementById("server.otrVerifyNudge").value = + this.account.otrVerifyNudge; + document.getElementById("server.otrRequireEncryption").value = + this.account.otrRequireEncryption; + + let fpa = this.account.normalizedName; + let fpp = this.account.protocol.normalizedName; + let fp = OTR.privateKeyFingerprint(fpa, fpp); + if (!fp) { + fp = await document.l10n.formatValue("otr-not-yet-available"); + } + document.getElementById("otrFingerprint").value = fp; + } + document.querySelector(".chat-encryption-settings").hidden = + !this.account.protocol.canEncrypt; + if (this.account.protocol.canEncrypt) { + document.l10n.setAttributes( + document.getElementById("chat-encryption-description"), + "chat-encryption-description", + { + protocol: this.proto.name, + } + ); + this.buildEncryptionStatus(); + this.buildAccountSessionsList(); + this.encryptionObserver = { + observe: (subject, topic) => { + if ( + topic === "account-sessions-changed" && + subject.id === this.account.id + ) { + this.buildAccountSessionsList(); + } else if ( + topic === "account-encryption-status-changed" && + subject.id === this.account.id + ) { + this.buildEncryptionStatus(); + } + }, + QueryInterface: ChromeUtils.generateQI([ + "nsIObserver", + "nsISupportsWeakReference", + ]), + }; + Services.obs.addObserver( + this.encryptionObserver, + "account-sessions-changed", + true + ); + Services.obs.addObserver( + this.encryptionObserver, + "account-encryption-status-changed", + true + ); + } + } + + let protoId = this.proto.id; + let canAutoJoin = + protoId == "prpl-irc" || + protoId == "prpl-jabber" || + protoId == "prpl-gtalk"; + document.getElementById("autojoinBox").hidden = !canAutoJoin; + let autojoin = document.getElementById("server.autojoin"); + if (canAutoJoin) { + autojoin.setAttribute("wsm_persist", "true"); + } else { + autojoin.removeAttribute("wsm_persist"); + } + + this.prefs = Services.prefs.getBranch( + "messenger.account." + this.account.id + ".options." + ); + this.populateProtoSpecificBox(); + }, + + encryptionObserver: null, + buildEncryptionStatus() { + const encryptionStatus = document.querySelector(".chat-encryption-status"); + if (this.account.encryptionStatus.length) { + encryptionStatus.replaceChildren( + ...this.account.encryptionStatus.map(status => { + const item = document.createElementNS( + "http://www.w3.org/1999/xhtml", + "li" + ); + item.textContent = status; + return item; + }) + ); + } else { + const placeholder = document.createElementNS( + "http://www.w3.org/1999/xhtml", + "li" + ); + document.l10n.setAttributes(placeholder, "chat-encryption-placeholder"); + encryptionStatus.replaceChildren(placeholder); + } + }, + buildAccountSessionsList() { + const sessions = this.account.getSessions(); + document.querySelector(".chat-encryption-sessions-container").hidden = + sessions.length === 0; + const sessionList = document.querySelector(".chat-encryption-sessions"); + sessionList.replaceChildren( + ...sessions.map(session => { + const button = document.createElementNS( + "http://www.w3.org/1999/xhtml", + "button" + ); + document.l10n.setAttributes( + button, + "chat-encryption-session-" + (session.trusted ? "trusted" : "verify") + ); + button.disabled = session.trusted; + if (!button.disabled) { + button.addEventListener("click", async () => { + try { + const sessionInfo = await session.verify(); + parent.gSubDialog.open( + "chrome://messenger/content/chat/verify.xhtml", + { features: "resizable=no" }, + sessionInfo + ); + } catch (error) { + // Verification was probably aborted by the other side. + this.account.prplAccount.wrappedJSObject.WARN(error); + } + }); + } + const sessionLabel = document.createElementNS( + "http://www.w3.org/1999/xhtml", + "span" + ); + sessionLabel.textContent = session.id; + const row = document.createElementNS( + "http://www.w3.org/1999/xhtml", + "li" + ); + row.append(sessionLabel, button); + row.classList.toggle("chat-current-session", session.currentSession); + return row; + }) + ); + }, + + populateProtoSpecificBox() { + let attributes = {}; + attributes[Ci.prplIPref.typeBool] = [ + { name: "wsm_persist", value: "true" }, + { name: "preftype", value: "bool" }, + { name: "genericattr", value: "true" }, + ]; + attributes[Ci.prplIPref.typeInt] = [ + { name: "wsm_persist", value: "true" }, + { name: "preftype", value: "int" }, + { name: "genericattr", value: "true" }, + ]; + attributes[Ci.prplIPref.typeString] = attributes[Ci.prplIPref.typeList] = [ + { name: "wsm_persist", value: "true" }, + { name: "preftype", value: "wstring" }, + { name: "genericattr", value: "true" }, + ]; + let haveOptions = accountOptionsHelper.addOptions( + "server.", + this.proto.getOptions(), + attributes + ); + let advanced = document.getElementById("advanced"); + if (advanced.hidden && haveOptions) { + advanced.hidden = false; + // Force textbox XBL binding attachment by forcing layout, + // otherwise setFormElementValue from AccountManager.js sets + // properties that don't exist when restoring values. + document.getElementById("protoSpecific").getBoundingClientRect(); + } else if (!haveOptions) { + advanced.hidden = true; + } + let inputElements = document.querySelectorAll( + "#protoSpecific :is(checkbox, input, menulist)" + ); + // Because the elements are added after the document loaded we have to + // notify the parent document that there are prefs to save. + for (let input of inputElements) { + if (input.localName == "input" || input.localName == "textarea") { + input.addEventListener("change", event => { + document.dispatchEvent(new CustomEvent("prefchange")); + }); + } else { + input.addEventListener("command", event => { + document.dispatchEvent(new CustomEvent("prefchange")); + }); + } + } + }, + + viewFingerprintKeys() { + let otrAccount = { account: this.account }; + parent.gSubDialog.open( + "chrome://chat/content/otr-finger.xhtml", + undefined, + otrAccount + ); + }, +}; |