dom/messages/SystemMessagePermissionsChecker.jsm

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 "use strict";
     7 const Ci = Components.interfaces;
     8 const Cu = Components.utils;
    10 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    11 Cu.import("resource://gre/modules/Services.jsm");
    12 Cu.import("resource://gre/modules/AppsUtils.jsm");
    13 Cu.import("resource://gre/modules/PermissionsInstaller.jsm");
    14 Cu.import("resource://gre/modules/PermissionsTable.jsm");
    15 Cu.import("resource://gre/modules/PermissionSettings.jsm");
    17 this.EXPORTED_SYMBOLS = ["SystemMessagePermissionsChecker",
    18                          "SystemMessagePermissionsTable"];
    20 function debug(aStr) {
    21   // dump("SystemMessagePermissionsChecker.jsm: " + aStr + "\n");
    22 }
    24 // This table maps system message to permission(s), indicating only
    25 // the system messages granted by the page's permissions are allowed
    26 // to be registered or sent to that page. Note the empty permission
    27 // set means this type of system message is always permitted.
    29 this.SystemMessagePermissionsTable = {
    30   "activity": { },
    31   "alarm": {
    32     "alarms": []
    33   },
    34   "bluetooth-dialer-command": {
    35     "telephony": []
    36   },
    37   "bluetooth-cancel": {
    38     "bluetooth": []
    39   },
    40   "bluetooth-hid-status-changed": {
    41     "bluetooth": []
    42   },
    43   "bluetooth-pairing-request": {
    44     "bluetooth": []
    45   },
    46   "bluetooth-opp-transfer-complete": {
    47     "bluetooth": []
    48   },
    49   "bluetooth-opp-update-progress": {
    50     "bluetooth": []
    51   },
    52   "bluetooth-opp-receiving-file-confirmation": {
    53     "bluetooth": []
    54   },
    55   "bluetooth-opp-transfer-start": {
    56     "bluetooth": []
    57   },
    58   "connection": { },
    59   "dummy-system-message": { }, // for system message testing framework
    60   "headset-button": { },
    61   "icc-stkcommand": {
    62     "settings": ["read", "write"]
    63   },
    64   "media-button": { },
    65   "networkstats-alarm": {
    66     "networkstats-manage": []
    67   },
    68   "notification": {
    69     "desktop-notification": []
    70   },
    71   "push": {
    72   	"push": []
    73   },
    74   "push-register": {
    75   	"push": []
    76   },
    77   "sms-delivery-success": {
    78     "sms": []
    79   },
    80   "sms-read-success": {
    81     "sms": []
    82   },
    83   "sms-received": {
    84     "sms": []
    85   },
    86   "sms-sent": {
    87     "sms": []
    88   },
    89   "telephony-new-call": {
    90     "telephony": []
    91   },
    92   "telephony-call-ended": {
    93     "telephony": []
    94   },
    95   "ussd-received": {
    96     "mobileconnection": []
    97   },
    98   "wappush-received": {
    99     "wappush": []
   100   },
   101   "cdma-info-rec-received": {
   102     "mobileconnection": []
   103   },
   104   "nfc-manager-tech-discovered": {
   105     "nfc-manager": []
   106   },
   107   "nfc-manager-tech-lost": {
   108     "nfc-manager": []
   109   },
   110   "nfc-manager-send-file": {
   111     "nfc-manager": []
   112   },
   113   "nfc-powerlevel-change": {
   114     "settings": ["read", "write"]
   115   },
   116   "wifip2p-pairing-request": { },
   117   "first-run-with-sim": {
   118     "settings": ["read", "write"]
   119   }
   120 };
   122 this.SystemMessagePermissionsChecker = {
   123   /**
   124    * Return all the needed permission names for the given system message.
   125    * @param string aSysMsgName
   126    *        The system messsage name.
   127    * @returns object
   128    *        Format: { permName (string): permNamesWithAccess (string array), ... }
   129    *        Ex, { "settings": ["settings-read", "settings-write"], ... }.
   130    *        Note: an empty object will be returned if it's always permitted.
   131    * @returns null
   132    *        Return and report error when any unexpected error is ecountered.
   133    *        Ex, when the system message we want to search is not included.
   134    **/
   135   getSystemMessagePermissions: function getSystemMessagePermissions(aSysMsgName) {
   136     debug("getSystemMessagePermissions(): aSysMsgName: " + aSysMsgName);
   138     let permNames = SystemMessagePermissionsTable[aSysMsgName];
   139     if (permNames === undefined) {
   140       debug("'" + aSysMsgName + "' is not associated with permissions. " +
   141             "Please add them to the SystemMessagePermissionsTable.");
   142       return null;
   143     }
   145     let object = { };
   146     for (let permName in permNames) {
   147       if (PermissionsTable[permName] === undefined) {
   148         debug("'" + permName + "' for '" + aSysMsgName + "' is invalid. " +
   149               "Please correct it in the SystemMessagePermissionsTable.");
   150         return null;
   151       }
   153       // Construct a new permission name array by adding the access suffixes.
   154       let access = permNames[permName];
   155       if (!access || !Array.isArray(access)) {
   156         debug("'" + permName + "' is not associated with access array. " +
   157               "Please correct it in the SystemMessagePermissionsTable.");
   158         return null;
   159       }
   160       object[permName] = appendAccessToPermName(permName, access);
   161     }
   162     return object
   163   },
   165   /**
   166    * Check if the system message is permitted to be registered for the given
   167    * app at start-up based on the permissions claimed in the app's manifest.
   168    * @param string aSysMsgName
   169    *        The system messsage name.
   170    * @param string aOrigin
   171    *        The app's origin.
   172    * @param object aManifest
   173    *        The app's manifest.
   174    * @returns bool
   175    *        Is permitted or not.
   176    **/
   177   isSystemMessagePermittedToRegister:
   178     function isSystemMessagePermittedToRegister(aSysMsgName, aOrigin, aManifest) {
   179     debug("isSystemMessagePermittedToRegister(): " +
   180           "aSysMsgName: " + aSysMsgName + ", " +
   181           "aOrigin: " + aOrigin + ", " +
   182           "aManifest: " + JSON.stringify(aManifest));
   184     let permNames = this.getSystemMessagePermissions(aSysMsgName);
   185     if (permNames === null) {
   186       return false;
   187     }
   189     // Check to see if the 'webapp' is app/privileged/certified.
   190     let appStatus;
   191     switch (AppsUtils.getAppManifestStatus(aManifest)) {
   192     case Ci.nsIPrincipal.APP_STATUS_CERTIFIED:
   193       appStatus = "certified";
   194       break;
   195     case Ci.nsIPrincipal.APP_STATUS_PRIVILEGED:
   196       appStatus = "privileged";
   197       break;
   198     case Ci.nsIPrincipal.APP_STATUS_INSTALLED:
   199       appStatus = "app";
   200       break;
   201     default:
   202       throw new Error("SystemMessagePermissionsChecker.jsm: " +
   203                       "Cannot decide the app's status. Install cancelled.");
   204       break;
   205     }
   207     let newManifest = new ManifestHelper(aManifest, aOrigin);
   209     for (let permName in permNames) {
   210       // The app doesn't claim valid permissions for this sytem message.
   211       if (!newManifest.permissions || !newManifest.permissions[permName]) {
   212         debug("'" + aSysMsgName + "' isn't permitted by '" + permName + "'. " +
   213               "Please add the permission for app: '" + aOrigin + "'.");
   214         return false;
   215       }
   216       let permValue = PermissionsTable[permName][appStatus];
   217       if (permValue != Ci.nsIPermissionManager.PROMPT_ACTION &&
   218           permValue != Ci.nsIPermissionManager.ALLOW_ACTION) {
   219         debug("'" + aSysMsgName + "' isn't permitted by '" + permName + "'. " +
   220               "Please add the permission for app: '" + aOrigin + "'.");
   221         return false;
   222       }
   224       // Compare the expanded permission names between the ones in
   225       // app's manifest and the ones needed for system message.
   226       let expandedPermNames =
   227         expandPermissions(permName,
   228                           newManifest.permissions[permName].access);
   230       let permNamesWithAccess = permNames[permName];
   232       // Early return false as soon as any permission is not matched.
   233       for (let idx in permNamesWithAccess) {
   234         let index = expandedPermNames.indexOf(permNamesWithAccess[idx]);
   235         if (index == -1) {
   236           debug("'" + aSysMsgName + "' isn't permitted by '" + permName + "'. " +
   237                 "Please add the permission for app: '" + aOrigin + "'.");
   238           return false;
   239         }
   240       }
   241     }
   243     // All the permissions needed for this system message are matched.
   244     return true;
   245   },
   247   /**
   248    * Check if the system message is permitted to be sent to the given
   249    * app's page at run-time based on the current app's permissions.
   250    * @param string aSysMsgName
   251    *        The system messsage name.
   252    * @param string aPageURL
   253    *        The app's page URL.
   254    * @param string aManifestURL
   255    *        The app's manifest URL.
   256    * @returns bool
   257    *        Is permitted or not.
   258    **/
   259   isSystemMessagePermittedToSend:
   260     function isSystemMessagePermittedToSend(aSysMsgName, aPageURL, aManifestURL) {
   261     debug("isSystemMessagePermittedToSend(): " +
   262           "aSysMsgName: " + aSysMsgName + ", " +
   263           "aPageURL: " + aPageURL + ", " +
   264           "aManifestURL: " + aManifestURL);
   266     let permNames = this.getSystemMessagePermissions(aSysMsgName);
   267     if (permNames === null) {
   268       return false;
   269     }
   271     let pageURI = Services.io.newURI(aPageURL, null, null);
   272     for (let permName in permNames) {
   273       let permNamesWithAccess = permNames[permName];
   275       // Early return false as soon as any permission is not matched.
   276       for (let idx in permNamesWithAccess) {
   277         if(PermissionSettingsModule.getPermission(permNamesWithAccess[idx],
   278                                                   aManifestURL,
   279                                                   pageURI.prePath,
   280                                                   false) != "allow") {
   281           debug("'" + aSysMsgName + "' isn't permitted by '" + permName + "'. " +
   282                 "Please add the permission for app: '" + pageURI.prePath + "'.");
   283           return false;
   284         }
   285       }
   286     }
   288     // All the permissions needed for this system message are matched.
   289     return true;
   290   }
   291 };

mercurial