summaryrefslogtreecommitdiffstats
path: root/dom/apps/PermissionsTable.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'dom/apps/PermissionsTable.jsm')
-rw-r--r--dom/apps/PermissionsTable.jsm593
1 files changed, 593 insertions, 0 deletions
diff --git a/dom/apps/PermissionsTable.jsm b/dom/apps/PermissionsTable.jsm
new file mode 100644
index 000000000..7c6a8490f
--- /dev/null
+++ b/dom/apps/PermissionsTable.jsm
@@ -0,0 +1,593 @@
+/* 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";
+
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+this.EXPORTED_SYMBOLS = [
+ "PermissionsTable",
+ "PermissionsReverseTable",
+ "expandPermissions",
+ "appendAccessToPermName",
+ "isExplicitInPermissionsTable",
+ "AllPossiblePermissions"
+];
+
+// Permission access flags
+const READONLY = "readonly";
+const CREATEONLY = "createonly";
+const READCREATE = "readcreate";
+const READWRITE = "readwrite";
+
+const UNKNOWN_ACTION = Ci.nsIPermissionManager.UNKNOWN_ACTION;
+const ALLOW_ACTION = Ci.nsIPermissionManager.ALLOW_ACTION;
+const DENY_ACTION = Ci.nsIPermissionManager.DENY_ACTION;
+const PROMPT_ACTION = Ci.nsIPermissionManager.PROMPT_ACTION;
+
+// Permissions Matrix: https://docs.google.com/spreadsheet/ccc?key=0Akyz_Bqjgf5pdENVekxYRjBTX0dCXzItMnRyUU1RQ0E#gid=0
+
+// Permissions that are implicit:
+// battery-status, network-information, vibration,
+// device-capabilities
+
+this.PermissionsTable = { geolocation: {
+ app: PROMPT_ACTION,
+ privileged: PROMPT_ACTION,
+ certified: PROMPT_ACTION
+ },
+ "geolocation-noprompt": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION,
+ substitute: ["geolocation"]
+ },
+ camera: {
+ app: DENY_ACTION,
+ privileged: PROMPT_ACTION,
+ certified: ALLOW_ACTION
+ },
+ alarms: {
+ app: ALLOW_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "tcp-socket": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "udp-socket": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "network-events": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ contacts: {
+ app: DENY_ACTION,
+ privileged: PROMPT_ACTION,
+ certified: ALLOW_ACTION,
+ access: ["read", "write", "create"]
+ },
+ "device-storage:apps": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION,
+ access: ["read"]
+ },
+ "device-storage:crashes": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION,
+ access: ["read"]
+ },
+ "device-storage:pictures": {
+ app: DENY_ACTION,
+ privileged: PROMPT_ACTION,
+ certified: ALLOW_ACTION,
+ access: ["read", "write", "create"]
+ },
+ "device-storage:videos": {
+ app: DENY_ACTION,
+ privileged: PROMPT_ACTION,
+ certified: ALLOW_ACTION,
+ access: ["read", "write", "create"]
+ },
+ "device-storage:music": {
+ app: DENY_ACTION,
+ privileged: PROMPT_ACTION,
+ certified: ALLOW_ACTION,
+ access: ["read", "write", "create"]
+ },
+ "device-storage:sdcard": {
+ app: DENY_ACTION,
+ privileged: PROMPT_ACTION,
+ certified: ALLOW_ACTION,
+ access: ["read", "write", "create"]
+ },
+ sms: {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "speech-recognition": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ browser: {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "browser:universalxss": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "browser:embedded-system-app": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ mobilenetwork: {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ power: {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ push: {
+ app: ALLOW_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ settings: {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION,
+ access: ["read", "write"],
+ additional: ["indexedDB-chrome-settings", "settings-api"]
+ },
+ // This exists purely for tests, no app
+ // should ever use it. It can only be
+ // handed out by SpecialPowers.
+ "settings-clear": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: DENY_ACTION,
+ additional: ["indexedDB-chrome-settings", "settings-api"]
+ },
+ permissions: {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ attention: {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "global-clickthrough-overlay": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "moz-attention": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION,
+ substitute: ["attention"]
+ },
+ "webapps-manage": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "homescreen-webapps-manage": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "backgroundservice": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "desktop-notification": {
+ app: ALLOW_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "networkstats-manage": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "wifi-manage": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "systemXHR": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "idle": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "time": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "embed-apps": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "background-sensors": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "audio-channel-normal": {
+ app: ALLOW_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "audio-channel-content": {
+ app: ALLOW_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "audio-channel-notification": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "audio-channel-alarm": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "audio-channel-system": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "audio-channel-telephony": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "moz-audio-channel-telephony": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION,
+ substitute: ["audio-channel-telephony"]
+ },
+ "audio-channel-ringer": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "moz-audio-channel-ringer": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION,
+ substitute: ["audio-channel-ringer"]
+ },
+ "audio-channel-publicnotification": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "open-remote-window": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "input": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "input-manage": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "audio-capture": {
+ app: PROMPT_ACTION,
+ privileged: PROMPT_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "audio-capture:3gpp": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "audio-capture:3gpp2": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "speaker-control": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "downloads": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "video-capture": {
+ app: PROMPT_ACTION,
+ privileged: PROMPT_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "feature-detection": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ // This permission doesn't actually grant access to
+ // anything. It exists only to check the correctness
+ // of web prompt composed permissions in tests.
+ "test-permission": {
+ app: PROMPT_ACTION,
+ privileged: PROMPT_ACTION,
+ certified: ALLOW_ACTION,
+ access: ["read", "write", "create"]
+ },
+ "firefox-accounts": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "moz-firefox-accounts": {
+ app: DENY_ACTION,
+ privileged: PROMPT_ACTION,
+ certified: ALLOW_ACTION,
+ substitute: ["firefox-accounts"]
+ },
+ "themeable": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "settings:wallpaper.image": {
+ app: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION,
+ access: ["read", "write"],
+ additional: ["settings-api"]
+ },
+ "tv": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "before-after-keyboard-event": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "presentation-device-manage": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "secureelement-manage": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "inputport": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "system-update": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "open-hidden-window": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "moz-extremely-unstable-and-will-change-webcomponents": {
+ app: DENY_ACTION,
+ trusted: DENY_ACTION,
+ privileged: ALLOW_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "system-app-only-audio-channels-in-app": {
+ app: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ },
+ "previously-certified-app": {
+ app: DENY_ACTION,
+ trusted: DENY_ACTION,
+ privileged: DENY_ACTION,
+ certified: ALLOW_ACTION
+ }
+ };
+
+/**
+ * Append access modes to the permission name as suffixes.
+ * e.g. permission name 'contacts' with ['read', 'write'] =
+ * ['contacts-read', contacts-write']
+ * @param string aPermName
+ * @param array aAccess
+ * @returns array containing access-appended permission names.
+ **/
+this.appendAccessToPermName = function appendAccessToPermName(aPermName, aAccess) {
+ if (aAccess.length == 0) {
+ return [aPermName];
+ }
+ return aAccess.map(function(aMode) {
+ return aPermName + "-" + aMode;
+ });
+};
+
+/**
+ * Expand an access string into multiple permission names,
+ * e.g: permission name 'contacts' with 'readwrite' =
+ * ['contacts-read', 'contacts-create', 'contacts-write']
+ * @param string aPermName
+ * @param string aAccess (optional)
+ * @returns array containing expanded permission names.
+ **/
+this.expandPermissions = function expandPermissions(aPermName, aAccess) {
+ if (!PermissionsTable[aPermName]) {
+ let errorMsg =
+ "PermissionsTable.jsm: expandPermissions: Unknown Permission: " + aPermName;
+ Cu.reportError(errorMsg);
+ dump(errorMsg);
+ return [];
+ }
+
+ const tableEntry = PermissionsTable[aPermName];
+
+ if (tableEntry.substitute && tableEntry.additional) {
+ let errorMsg =
+ "PermissionsTable.jsm: expandPermissions: Can't handle both 'substitute' " +
+ "and 'additional' entries for permission: " + aPermName;
+ Cu.reportError(errorMsg);
+ dump(errorMsg);
+ return [];
+ }
+
+ if (!aAccess && tableEntry.access ||
+ aAccess && !tableEntry.access) {
+ let errorMsg =
+ "PermissionsTable.jsm: expandPermissions: Invalid access for permission " +
+ aPermName + ": " + aAccess + "\n";
+ Cu.reportError(errorMsg);
+ dump(errorMsg);
+ return [];
+ }
+
+ let expandedPermNames = [];
+
+ if (tableEntry.access && aAccess) {
+ let requestedSuffixes = [];
+ switch (aAccess) {
+ case READONLY:
+ requestedSuffixes.push("read");
+ break;
+ case CREATEONLY:
+ requestedSuffixes.push("create");
+ break;
+ case READCREATE:
+ requestedSuffixes.push("read", "create");
+ break;
+ case READWRITE:
+ requestedSuffixes.push("read", "create", "write");
+ break;
+ default:
+ return [];
+ }
+
+ let permArr = appendAccessToPermName(aPermName, requestedSuffixes);
+
+ // Add the same suffix to each of the additions.
+ if (tableEntry.additional) {
+ for (let additional of tableEntry.additional) {
+ permArr = permArr.concat(appendAccessToPermName(additional, requestedSuffixes));
+ }
+ }
+
+ // Only add the suffixed version if the suffix exists in the table.
+ for (let idx in permArr) {
+ let suffix = requestedSuffixes[idx % requestedSuffixes.length];
+ if (tableEntry.access.indexOf(suffix) != -1) {
+ expandedPermNames.push(permArr[idx]);
+ }
+ }
+ } else if (tableEntry.substitute) {
+ expandedPermNames = expandedPermNames.concat(tableEntry.substitute);
+ } else {
+ expandedPermNames.push(aPermName);
+ // Include each of the additions exactly as they appear in the table.
+ if (tableEntry.additional) {
+ expandedPermNames = expandedPermNames.concat(tableEntry.additional);
+ }
+ }
+
+ return expandedPermNames;
+};
+
+this.PermissionsReverseTable = {};
+this.AllPossiblePermissions = [];
+
+(function () {
+ // PermissionsTable as it is works well for direct searches, but not
+ // so well for reverse ones (that is, if I get something like
+ // device-storage:music-read or indexedDB-chrome-settings-read how
+ // do I know which permission it really is? Hence this table is
+ // born. The idea is that
+ // reverseTable[device-storage:music-read] should return
+ // device-storage:music
+ //
+ // We also need a list of all the possible permissions for things like the
+ // settingsmanager, so construct that while we're at it.
+ for (let permName in PermissionsTable) {
+ let permAliases = [];
+ if (PermissionsTable[permName].access) {
+ permAliases = expandPermissions(permName, "readwrite");
+ } else if (!PermissionsTable[permName].substitute) {
+ permAliases = expandPermissions(permName);
+ }
+ for (let i = 0; i < permAliases.length; i++) {
+ PermissionsReverseTable[permAliases[i]] = permName;
+ AllPossiblePermissions.push(permAliases[i]);
+ }
+ }
+ AllPossiblePermissions =
+ AllPossiblePermissions.concat(["indexedDB", "offline-app", "pin-app"]);
+})();
+
+this.isExplicitInPermissionsTable = function(aPermName, aIntStatus) {
+
+ // Check to see if the 'webapp' is app/privileged/certified.
+ let appStatus;
+ switch (aIntStatus) {
+ case Ci.nsIPrincipal.APP_STATUS_CERTIFIED:
+ appStatus = "certified";
+ break;
+ case Ci.nsIPrincipal.APP_STATUS_PRIVILEGED:
+ appStatus = "privileged";
+ break;
+ default: // If it isn't certified or privileged, it's app
+ appStatus = "app";
+ break;
+ }
+
+ let realPerm = PermissionsReverseTable[aPermName];
+
+ if (realPerm) {
+ return (PermissionsTable[realPerm][appStatus] ==
+ Ci.nsIPermissionManager.PROMPT_ACTION);
+ } else {
+ return false;
+ }
+}