dom/alarm/AlarmsManager.js

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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 /* static functions */
     8 const DEBUG = false;
    10 function debug(aStr) {
    11   if (DEBUG)
    12     dump("AlarmsManager: " + aStr + "\n");
    13 }
    15 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
    17 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    18 Cu.import("resource://gre/modules/Services.jsm");
    19 Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
    21 const ALARMSMANAGER_CONTRACTID = "@mozilla.org/alarmsManager;1";
    22 const ALARMSMANAGER_CID        = Components.ID("{fea1e884-9b05-11e1-9b64-87a7016c3860}");
    23 const nsIDOMMozAlarmsManager   = Ci.nsIDOMMozAlarmsManager;
    24 const nsIClassInfo             = Ci.nsIClassInfo;
    26 function AlarmsManager()
    27 {
    28   debug("Constructor");
    29 }
    31 AlarmsManager.prototype = {
    33   __proto__: DOMRequestIpcHelper.prototype,
    35   classID : ALARMSMANAGER_CID,
    37   QueryInterface : XPCOMUtils.generateQI([nsIDOMMozAlarmsManager,
    38                                           Ci.nsIDOMGlobalPropertyInitializer,
    39                                           Ci.nsISupportsWeakReference,
    40                                           Ci.nsIObserver]),
    42   classInfo : XPCOMUtils.generateCI({ classID: ALARMSMANAGER_CID,
    43                                       contractID: ALARMSMANAGER_CONTRACTID,
    44                                       classDescription: "AlarmsManager",
    45                                       interfaces: [nsIDOMMozAlarmsManager],
    46                                       flags: nsIClassInfo.DOM_OBJECT }),
    48   add: function add(aDate, aRespectTimezone, aData) {
    49     debug("add()");
    51     if (!this._manifestURL) {
    52       debug("Cannot add alarms for non-installed apps.");
    53       throw Components.results.NS_ERROR_FAILURE;
    54     }
    56     if (!aDate) {
    57       throw Components.results.NS_ERROR_INVALID_ARG;
    58     }
    60     let isIgnoreTimezone = true;
    61     switch (aRespectTimezone) {
    62       case "honorTimezone":
    63         isIgnoreTimezone = false;
    64         break;
    66       case "ignoreTimezone":
    67         isIgnoreTimezone = true;
    68         break;
    70       default:
    71         throw Components.results.NS_ERROR_INVALID_ARG;
    72         break;
    73     }
    75     // Run JSON.stringify() in the sand box with the principal of the calling
    76     // web page to ensure no cross-origin object is involved. A "Permission
    77     // Denied" error will be thrown in case of privilege violation.
    78     let sandbox = new Cu.Sandbox(this._window.document.nodePrincipal);
    79     sandbox.data = aData;
    80     let data = Cu.evalInSandbox("JSON.stringify(data)", sandbox);
    81     let request = this.createRequest();
    82     this._cpmm.sendAsyncMessage(
    83       "AlarmsManager:Add",
    84       { requestId: this.getRequestId(request),
    85         date: aDate,
    86         ignoreTimezone: isIgnoreTimezone,
    87         data: JSON.parse(data),
    88         pageURL: this._pageURL,
    89         manifestURL: this._manifestURL }
    90     );
    91     return request;
    92   },
    94   remove: function remove(aId) {
    95     debug("remove()");
    97     this._cpmm.sendAsyncMessage(
    98       "AlarmsManager:Remove",
    99       { id: aId, manifestURL: this._manifestURL }
   100     );
   101   },
   103   getAll: function getAll() {
   104     debug("getAll()");
   106     let request = this.createRequest();
   107     this._cpmm.sendAsyncMessage(
   108       "AlarmsManager:GetAll",
   109       { requestId: this.getRequestId(request), manifestURL: this._manifestURL }
   110     );
   111     return request;
   112   },
   114   receiveMessage: function receiveMessage(aMessage) {
   115     debug("receiveMessage(): " + aMessage.name);
   117     let json = aMessage.json;
   118     let request = this.getRequest(json.requestId);
   120     if (!request) {
   121       debug("No request stored! " + json.requestId);
   122       return;
   123     }
   125     switch (aMessage.name) {
   126       case "AlarmsManager:Add:Return:OK":
   127         Services.DOMRequest.fireSuccess(request, json.id);
   128         break;
   130       case "AlarmsManager:GetAll:Return:OK":
   131         // We don't need to expose everything to the web content.
   132         let alarms = [];
   133         json.alarms.forEach(function trimAlarmInfo(aAlarm) {
   134           let alarm = { "id":              aAlarm.id,
   135                         "date":            aAlarm.date,
   136                         "respectTimezone": aAlarm.ignoreTimezone ?
   137                                              "ignoreTimezone" : "honorTimezone",
   138                         "data":            aAlarm.data };
   139           alarms.push(alarm);
   140         });
   141         Services.DOMRequest.fireSuccess(request,
   142                                         Cu.cloneInto(alarms, this._window));
   143         break;
   145       case "AlarmsManager:Add:Return:KO":
   146         Services.DOMRequest.fireError(request, json.errorMsg);
   147         break;
   149       case "AlarmsManager:GetAll:Return:KO":
   150         Services.DOMRequest.fireError(request, json.errorMsg);
   151         break;
   153       default:
   154         debug("Wrong message: " + aMessage.name);
   155         break;
   156     }
   157     this.removeRequest(json.requestId);
   158    },
   160   // nsIDOMGlobalPropertyInitializer implementation
   161   init: function init(aWindow) {
   162     debug("init()");
   164     // Set navigator.mozAlarms to null.
   165     if (!Services.prefs.getBoolPref("dom.mozAlarms.enabled")) {
   166       return null;
   167     }
   169     // Only pages with perm set can use the alarms.
   170     let principal = aWindow.document.nodePrincipal;
   171     let perm =
   172       Services.perms.testExactPermissionFromPrincipal(principal, "alarms");
   173     if (perm != Ci.nsIPermissionManager.ALLOW_ACTION) {
   174       return null;
   175     }
   177     // SystemPrincipal documents do not have any origin.
   178     // Reject them for now.
   179     if (!principal.URI) {
   180       return null;
   181     }
   183     this._cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
   184                    .getService(Ci.nsISyncMessageSender);
   186     // Add the valid messages to be listened.
   187     this.initDOMRequestHelper(aWindow, ["AlarmsManager:Add:Return:OK",
   188                                         "AlarmsManager:Add:Return:KO",
   189                                         "AlarmsManager:GetAll:Return:OK",
   190                                         "AlarmsManager:GetAll:Return:KO"]);
   192     // Get the manifest URL if this is an installed app
   193     let appsService = Cc["@mozilla.org/AppsService;1"]
   194                         .getService(Ci.nsIAppsService);
   195     this._pageURL = principal.URI.spec;
   196     this._manifestURL = appsService.getManifestURLByLocalId(principal.appId);
   197     this._window = aWindow;
   198   },
   200   // Called from DOMRequestIpcHelper.
   201   uninit: function uninit() {
   202     debug("uninit()");
   203   },
   204 }
   206 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AlarmsManager])

mercurial