123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594 |
- /* 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;
- }
- }
|