michael@0: /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: const nsIPermissionManager = Components.interfaces.nsIPermissionManager; michael@0: const nsICookiePermission = Components.interfaces.nsICookiePermission; michael@0: michael@0: const NOTIFICATION_FLUSH_PERMISSIONS = "flush-pending-permissions"; michael@0: michael@0: function Permission(host, rawHost, type, capability) michael@0: { michael@0: this.host = host; michael@0: this.rawHost = rawHost; michael@0: this.type = type; michael@0: this.capability = capability; michael@0: } michael@0: michael@0: var gPermissionManager = { michael@0: _type : "", michael@0: _permissions : [], michael@0: _pm : Components.classes["@mozilla.org/permissionmanager;1"] michael@0: .getService(Components.interfaces.nsIPermissionManager), michael@0: _bundle : null, michael@0: _tree : null, michael@0: michael@0: _view: { michael@0: _rowCount: 0, michael@0: get rowCount() michael@0: { michael@0: return this._rowCount; michael@0: }, michael@0: getCellText: function (aRow, aColumn) michael@0: { michael@0: if (aColumn.id == "siteCol") michael@0: return gPermissionManager._permissions[aRow].rawHost; michael@0: else if (aColumn.id == "statusCol") michael@0: return gPermissionManager._permissions[aRow].capability; michael@0: return ""; michael@0: }, michael@0: michael@0: isSeparator: function(aIndex) { return false; }, michael@0: isSorted: function() { return false; }, michael@0: isContainer: function(aIndex) { return false; }, michael@0: setTree: function(aTree){}, michael@0: getImageSrc: function(aRow, aColumn) {}, michael@0: getProgressMode: function(aRow, aColumn) {}, michael@0: getCellValue: function(aRow, aColumn) {}, michael@0: cycleHeader: function(column) {}, michael@0: getRowProperties: function(row){ return ""; }, michael@0: getColumnProperties: function(column){ return ""; }, michael@0: getCellProperties: function(row,column){ michael@0: if (column.element.getAttribute("id") == "siteCol") michael@0: return "ltr"; michael@0: michael@0: return ""; michael@0: } michael@0: }, michael@0: michael@0: _getCapabilityString: function (aCapability) michael@0: { michael@0: var stringKey = null; michael@0: switch (aCapability) { michael@0: case nsIPermissionManager.ALLOW_ACTION: michael@0: stringKey = "can"; michael@0: break; michael@0: case nsIPermissionManager.DENY_ACTION: michael@0: stringKey = "cannot"; michael@0: break; michael@0: case nsICookiePermission.ACCESS_ALLOW_FIRST_PARTY_ONLY: michael@0: stringKey = "canAccessFirstParty"; michael@0: break; michael@0: case nsICookiePermission.ACCESS_SESSION: michael@0: stringKey = "canSession"; michael@0: break; michael@0: } michael@0: return this._bundle.getString(stringKey); michael@0: }, michael@0: michael@0: addPermission: function (aCapability) michael@0: { michael@0: var textbox = document.getElementById("url"); michael@0: var host = textbox.value.replace(/^\s*([-\w]*:\/+)?/, ""); // trim any leading space and scheme michael@0: try { michael@0: var ioService = Components.classes["@mozilla.org/network/io-service;1"] michael@0: .getService(Components.interfaces.nsIIOService); michael@0: var uri = ioService.newURI("http://"+host, null, null); michael@0: host = uri.host; michael@0: } catch(ex) { michael@0: var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] michael@0: .getService(Components.interfaces.nsIPromptService); michael@0: var message = this._bundle.getString("invalidURI"); michael@0: var title = this._bundle.getString("invalidURITitle"); michael@0: promptService.alert(window, title, message); michael@0: return; michael@0: } michael@0: michael@0: var capabilityString = this._getCapabilityString(aCapability); michael@0: michael@0: // check whether the permission already exists, if not, add it michael@0: var exists = false; michael@0: for (var i = 0; i < this._permissions.length; ++i) { michael@0: if (this._permissions[i].rawHost == host) { michael@0: // Avoid calling the permission manager if the capability settings are michael@0: // the same. Otherwise allow the call to the permissions manager to michael@0: // update the listbox for us. michael@0: exists = this._permissions[i].capability == capabilityString; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: if (!exists) { michael@0: host = (host.charAt(0) == ".") ? host.substring(1,host.length) : host; michael@0: var uri = ioService.newURI("http://" + host, null, null); michael@0: this._pm.add(uri, this._type, aCapability); michael@0: } michael@0: textbox.value = ""; michael@0: textbox.focus(); michael@0: michael@0: // covers a case where the site exists already, so the buttons don't disable michael@0: this.onHostInput(textbox); michael@0: michael@0: // enable "remove all" button as needed michael@0: document.getElementById("removeAllPermissions").disabled = this._permissions.length == 0; michael@0: }, michael@0: michael@0: onHostInput: function (aSiteField) michael@0: { michael@0: document.getElementById("btnSession").disabled = !aSiteField.value; michael@0: document.getElementById("btnBlock").disabled = !aSiteField.value; michael@0: document.getElementById("btnAllow").disabled = !aSiteField.value; michael@0: }, michael@0: michael@0: onWindowKeyPress: function (aEvent) michael@0: { michael@0: if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE) michael@0: window.close(); michael@0: }, michael@0: michael@0: onHostKeyPress: function (aEvent) michael@0: { michael@0: if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN) michael@0: document.getElementById("btnAllow").click(); michael@0: }, michael@0: michael@0: onLoad: function () michael@0: { michael@0: this._bundle = document.getElementById("bundlePreferences"); michael@0: var params = window.arguments[0]; michael@0: this.init(params); michael@0: }, michael@0: michael@0: init: function (aParams) michael@0: { michael@0: if (this._type) { michael@0: // reusing an open dialog, clear the old observer michael@0: this.uninit(); michael@0: } michael@0: michael@0: this._type = aParams.permissionType; michael@0: this._manageCapability = aParams.manageCapability; michael@0: michael@0: var permissionsText = document.getElementById("permissionsText"); michael@0: while (permissionsText.hasChildNodes()) michael@0: permissionsText.removeChild(permissionsText.firstChild); michael@0: permissionsText.appendChild(document.createTextNode(aParams.introText)); michael@0: michael@0: document.title = aParams.windowTitle; michael@0: michael@0: document.getElementById("btnBlock").hidden = !aParams.blockVisible; michael@0: document.getElementById("btnSession").hidden = !aParams.sessionVisible; michael@0: document.getElementById("btnAllow").hidden = !aParams.allowVisible; michael@0: michael@0: var urlFieldVisible = (aParams.blockVisible || aParams.sessionVisible || aParams.allowVisible); michael@0: michael@0: var urlField = document.getElementById("url"); michael@0: urlField.value = aParams.prefilledHost; michael@0: urlField.hidden = !urlFieldVisible; michael@0: michael@0: this.onHostInput(urlField); michael@0: michael@0: var urlLabel = document.getElementById("urlLabel"); michael@0: urlLabel.hidden = !urlFieldVisible; michael@0: michael@0: var os = Components.classes["@mozilla.org/observer-service;1"] michael@0: .getService(Components.interfaces.nsIObserverService); michael@0: os.notifyObservers(null, NOTIFICATION_FLUSH_PERMISSIONS, this._type); michael@0: os.addObserver(this, "perm-changed", false); michael@0: michael@0: this._loadPermissions(); michael@0: michael@0: urlField.focus(); michael@0: }, michael@0: michael@0: uninit: function () michael@0: { michael@0: var os = Components.classes["@mozilla.org/observer-service;1"] michael@0: .getService(Components.interfaces.nsIObserverService); michael@0: os.removeObserver(this, "perm-changed"); michael@0: }, michael@0: michael@0: observe: function (aSubject, aTopic, aData) michael@0: { michael@0: if (aTopic == "perm-changed") { michael@0: var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission); michael@0: if (aData == "added") { michael@0: this._addPermissionToList(permission); michael@0: ++this._view._rowCount; michael@0: this._tree.treeBoxObject.rowCountChanged(this._view.rowCount - 1, 1); michael@0: // Re-do the sort, since we inserted this new item at the end. michael@0: gTreeUtils.sort(this._tree, this._view, this._permissions, michael@0: this._permissionsComparator, michael@0: this._lastPermissionSortColumn, michael@0: this._lastPermissionSortAscending); michael@0: } michael@0: else if (aData == "changed") { michael@0: for (var i = 0; i < this._permissions.length; ++i) { michael@0: if (this._permissions[i].host == permission.host) { michael@0: this._permissions[i].capability = this._getCapabilityString(permission.capability); michael@0: break; michael@0: } michael@0: } michael@0: // Re-do the sort, if the status changed from Block to Allow michael@0: // or vice versa, since if we're sorted on status, we may no michael@0: // longer be in order. michael@0: if (this._lastPermissionSortColumn.id == "statusCol") { michael@0: gTreeUtils.sort(this._tree, this._view, this._permissions, michael@0: this._permissionsComparator, michael@0: this._lastPermissionSortColumn, michael@0: this._lastPermissionSortAscending); michael@0: } michael@0: this._tree.treeBoxObject.invalidate(); michael@0: } michael@0: // No UI other than this window causes this method to be sent a "deleted" michael@0: // notification, so we don't need to implement it since Delete is handled michael@0: // directly by the Permission Removal handlers. If that ever changes, those michael@0: // implementations will have to move into here. michael@0: } michael@0: }, michael@0: michael@0: onPermissionSelected: function () michael@0: { michael@0: var hasSelection = this._tree.view.selection.count > 0; michael@0: var hasRows = this._tree.view.rowCount > 0; michael@0: document.getElementById("removePermission").disabled = !hasRows || !hasSelection; michael@0: document.getElementById("removeAllPermissions").disabled = !hasRows; michael@0: }, michael@0: michael@0: onPermissionDeleted: function () michael@0: { michael@0: if (!this._view.rowCount) michael@0: return; michael@0: var removedPermissions = []; michael@0: gTreeUtils.deleteSelectedItems(this._tree, this._view, this._permissions, removedPermissions); michael@0: for (var i = 0; i < removedPermissions.length; ++i) { michael@0: var p = removedPermissions[i]; michael@0: this._pm.remove(p.host, p.type); michael@0: } michael@0: document.getElementById("removePermission").disabled = !this._permissions.length; michael@0: document.getElementById("removeAllPermissions").disabled = !this._permissions.length; michael@0: }, michael@0: michael@0: onAllPermissionsDeleted: function () michael@0: { michael@0: if (!this._view.rowCount) michael@0: return; michael@0: var removedPermissions = []; michael@0: gTreeUtils.deleteAll(this._tree, this._view, this._permissions, removedPermissions); michael@0: for (var i = 0; i < removedPermissions.length; ++i) { michael@0: var p = removedPermissions[i]; michael@0: this._pm.remove(p.host, p.type); michael@0: } michael@0: document.getElementById("removePermission").disabled = true; michael@0: document.getElementById("removeAllPermissions").disabled = true; michael@0: }, michael@0: michael@0: onPermissionKeyPress: function (aEvent) michael@0: { michael@0: if (aEvent.keyCode == 46) michael@0: this.onPermissionDeleted(); michael@0: }, michael@0: michael@0: _lastPermissionSortColumn: "", michael@0: _lastPermissionSortAscending: false, michael@0: _permissionsComparator : function (a, b) michael@0: { michael@0: return a.toLowerCase().localeCompare(b.toLowerCase()); michael@0: }, michael@0: michael@0: michael@0: onPermissionSort: function (aColumn) michael@0: { michael@0: this._lastPermissionSortAscending = gTreeUtils.sort(this._tree, michael@0: this._view, michael@0: this._permissions, michael@0: aColumn, michael@0: this._permissionsComparator, michael@0: this._lastPermissionSortColumn, michael@0: this._lastPermissionSortAscending); michael@0: this._lastPermissionSortColumn = aColumn; michael@0: }, michael@0: michael@0: _loadPermissions: function () michael@0: { michael@0: this._tree = document.getElementById("permissionsTree"); michael@0: this._permissions = []; michael@0: michael@0: // load permissions into a table michael@0: var count = 0; michael@0: var enumerator = this._pm.enumerator; michael@0: while (enumerator.hasMoreElements()) { michael@0: var nextPermission = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission); michael@0: this._addPermissionToList(nextPermission); michael@0: } michael@0: michael@0: this._view._rowCount = this._permissions.length; michael@0: michael@0: // sort and display the table michael@0: this._tree.treeBoxObject.view = this._view; michael@0: this.onPermissionSort("rawHost", false); michael@0: michael@0: // disable "remove all" button if there are none michael@0: document.getElementById("removeAllPermissions").disabled = this._permissions.length == 0; michael@0: }, michael@0: michael@0: _addPermissionToList: function (aPermission) michael@0: { michael@0: if (aPermission.type == this._type && michael@0: (!this._manageCapability || michael@0: (aPermission.capability == this._manageCapability))) { michael@0: michael@0: var host = aPermission.host; michael@0: var capabilityString = this._getCapabilityString(aPermission.capability); michael@0: var p = new Permission(host, michael@0: (host.charAt(0) == ".") ? host.substring(1,host.length) : host, michael@0: aPermission.type, michael@0: capabilityString); michael@0: this._permissions.push(p); michael@0: } michael@0: }, michael@0: michael@0: setHost: function (aHost) michael@0: { michael@0: document.getElementById("url").value = aHost; michael@0: } michael@0: }; michael@0: michael@0: function setHost(aHost) michael@0: { michael@0: gPermissionManager.setHost(aHost); michael@0: } michael@0: michael@0: function initWithParams(aParams) michael@0: { michael@0: gPermissionManager.init(aParams); michael@0: } michael@0: