summaryrefslogtreecommitdiffstats
path: root/comm/mail/components/im/content/am-im.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/components/im/content/am-im.js')
-rw-r--r--comm/mail/components/im/content/am-im.js291
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
+ );
+ },
+};