diff options
Diffstat (limited to 'browser/components/preferences/translation.js')
-rw-r--r-- | browser/components/preferences/translation.js | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/browser/components/preferences/translation.js b/browser/components/preferences/translation.js new file mode 100644 index 000000000..cd570db0e --- /dev/null +++ b/browser/components/preferences/translation.js @@ -0,0 +1,255 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */ +/* 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/. */ + +"use strict"; + +var {classes: Cc, interfaces: Ci, utils: Cu} = Components; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +XPCOMUtils.defineLazyGetter(this, "gLangBundle", () => + Services.strings.createBundle("chrome://global/locale/languageNames.properties")); + +const kPermissionType = "translate"; +const kLanguagesPref = "browser.translation.neverForLanguages"; + +function Tree(aId, aData) +{ + this._data = aData; + this._tree = document.getElementById(aId); + this._tree.view = this; +} + +Tree.prototype = { + get boxObject() { + return this._tree.treeBoxObject; + }, + get isEmpty() { + return !this._data.length; + }, + get hasSelection() { + return this.selection.count > 0; + }, + getSelectedItems: function() { + let result = []; + + let rc = this.selection.getRangeCount(); + for (let i = 0; i < rc; ++i) { + let min = {}, max = {}; + this.selection.getRangeAt(i, min, max); + for (let j = min.value; j <= max.value; ++j) + result.push(this._data[j]); + } + + return result; + }, + + // nsITreeView implementation + get rowCount() { + return this._data.length; + }, + getCellText: function (aRow, aColumn) { + return this._data[aRow]; + }, + isSeparator: function(aIndex) { + return false; + }, + isSorted: function() { + return false; + }, + isContainer: function(aIndex) { + return false; + }, + setTree: function(aTree) {}, + getImageSrc: function(aRow, aColumn) {}, + getProgressMode: function(aRow, aColumn) {}, + getCellValue: function(aRow, aColumn) {}, + cycleHeader: function(column) {}, + getRowProperties: function(row) { + return ""; + }, + getColumnProperties: function(column) { + return ""; + }, + getCellProperties: function(row, column) { + return ""; + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsITreeView]) +}; + +function Lang(aCode) +{ + this.langCode = aCode; + this._label = gLangBundle.GetStringFromName(aCode); +} + +Lang.prototype = { + toString: function() { + return this._label; + } +} + +var gTranslationExceptions = { + onLoad: function() { + if (this._siteTree) { + // Re-using an open dialog, clear the old observers. + this.uninit(); + } + + // Load site permissions into an array. + this._sites = []; + let enumerator = Services.perms.enumerator; + while (enumerator.hasMoreElements()) { + let perm = enumerator.getNext().QueryInterface(Ci.nsIPermission); + + if (perm.type == kPermissionType && + perm.capability == Services.perms.DENY_ACTION) { + this._sites.push(perm.principal.origin); + } + } + Services.obs.addObserver(this, "perm-changed", false); + this._sites.sort(); + + this._siteTree = new Tree("sitesTree", this._sites); + this.onSiteSelected(); + + this._langs = this.getLanguageExceptions(); + Services.prefs.addObserver(kLanguagesPref, this, false); + this._langTree = new Tree("languagesTree", this._langs); + this.onLanguageSelected(); + }, + + // Get the list of languages we don't translate as an array. + getLanguageExceptions: function() { + let langs = Services.prefs.getCharPref(kLanguagesPref); + if (!langs) + return []; + + let result = langs.split(",").map(code => new Lang(code)); + result.sort(); + + return result; + }, + + observe: function(aSubject, aTopic, aData) { + if (aTopic == "perm-changed") { + if (aData == "cleared") { + if (!this._sites.length) + return; + let removed = this._sites.splice(0, this._sites.length); + this._siteTree.boxObject.rowCountChanged(0, - removed.length); + } + else { + let perm = aSubject.QueryInterface(Ci.nsIPermission); + if (perm.type != kPermissionType) + return; + + if (aData == "added") { + if (perm.capability != Services.perms.DENY_ACTION) + return; + this._sites.push(perm.principal.origin); + this._sites.sort(); + let boxObject = this._siteTree.boxObject; + boxObject.rowCountChanged(0, 1); + boxObject.invalidate(); + } + else if (aData == "deleted") { + let index = this._sites.indexOf(perm.principal.origin); + if (index == -1) + return; + this._sites.splice(index, 1); + this._siteTree.boxObject.rowCountChanged(index, -1); + this.onSiteSelected(); + return; + } + } + this.onSiteSelected(); + } + else if (aTopic == "nsPref:changed") { + this._langs = this.getLanguageExceptions(); + let change = this._langs.length - this._langTree.rowCount; + this._langTree._data = this._langs; + let boxObject = this._langTree.boxObject; + if (change) + boxObject.rowCountChanged(0, change); + boxObject.invalidate(); + this.onLanguageSelected(); + } + }, + + _handleButtonDisabling: function(aTree, aIdPart) { + let empty = aTree.isEmpty; + document.getElementById("removeAll" + aIdPart + "s").disabled = empty; + document.getElementById("remove" + aIdPart).disabled = + empty || !aTree.hasSelection; + }, + + onLanguageSelected: function() { + this._handleButtonDisabling(this._langTree, "Language"); + }, + + onSiteSelected: function() { + this._handleButtonDisabling(this._siteTree, "Site"); + }, + + onLanguageDeleted: function() { + let langs = Services.prefs.getCharPref(kLanguagesPref); + if (!langs) + return; + + let removed = this._langTree.getSelectedItems().map(l => l.langCode); + + langs = langs.split(",").filter(l => removed.indexOf(l) == -1); + Services.prefs.setCharPref(kLanguagesPref, langs.join(",")); + }, + + onAllLanguagesDeleted: function() { + Services.prefs.setCharPref(kLanguagesPref, ""); + }, + + onSiteDeleted: function() { + let removedSites = this._siteTree.getSelectedItems(); + for (let origin of removedSites) { + let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin); + Services.perms.removeFromPrincipal(principal, kPermissionType); + } + }, + + onAllSitesDeleted: function() { + if (this._siteTree.isEmpty) + return; + + let removedSites = this._sites.splice(0, this._sites.length); + this._siteTree.boxObject.rowCountChanged(0, -removedSites.length); + + for (let origin of removedSites) { + let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin); + Services.perms.removeFromPrincipal(principal, kPermissionType); + } + + this.onSiteSelected(); + }, + + onSiteKeyPress: function(aEvent) { + if (aEvent.keyCode == KeyEvent.DOM_VK_DELETE) + this.onSiteDeleted(); + }, + + onLanguageKeyPress: function(aEvent) { + if (aEvent.keyCode == KeyEvent.DOM_VK_DELETE) + this.onLanguageDeleted(); + }, + + onWindowKeyPress: function(aEvent) { + if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE) + window.close(); + }, + + uninit: function() { + Services.obs.removeObserver(this, "perm-changed"); + Services.prefs.removeObserver(kLanguagesPref, this); + } +}; |