dom/downloads/src/DownloadsIPC.jsm

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 "use strict";
     7 const Cc = Components.classes;
     8 const Ci = Components.interfaces;
     9 const Cu = Components.utils;
    11 this.EXPORTED_SYMBOLS = ["DownloadsIPC"];
    13 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    14 Cu.import("resource://gre/modules/Services.jsm");
    15 Cu.import("resource://gre/modules/Promise.jsm");
    17 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
    18                                    "@mozilla.org/childprocessmessagemanager;1",
    19                                    "nsIMessageSender");
    21 /**
    22   * This module lives in the child process and receives the ipc messages
    23   * from the parent. It saves the download's state and redispatch changes
    24   * to DOM objects using an observer notification.
    25   *
    26   * This module needs to be loaded once and only once per process.
    27   */
    29 function debug(aStr) {
    30 #ifdef MOZ_DEBUG
    31   dump("-*- DownloadsIPC.jsm : " + aStr + "\n");
    32 #endif
    33 }
    35 const ipcMessages = ["Downloads:Added",
    36                      "Downloads:Removed",
    37                      "Downloads:Changed",
    38                      "Downloads:GetList:Return",
    39                      "Downloads:ClearAllDone:Return",
    40                      "Downloads:Remove:Return",
    41                      "Downloads:Pause:Return",
    42                      "Downloads:Resume:Return"];
    44 this.DownloadsIPC = {
    45   downloads: {},
    47   init: function() {
    48     debug("init");
    49     Services.obs.addObserver(this, "xpcom-shutdown", false);
    50     ipcMessages.forEach((aMessage) => {
    51       cpmm.addMessageListener(aMessage, this);
    52     });
    54     // We need to get the list of current downloads.
    55     this.ready = false;
    56     this.getListPromises = [];
    57     this.clearAllPromises = [];
    58     this.downloadPromises = {};
    59     cpmm.sendAsyncMessage("Downloads:GetList", {});
    60     this._promiseId = 0;
    61   },
    63   notifyChanges: function(aId) {
    64     // TODO: use the subject instead of stringifying.
    65     if (this.downloads[aId]) {
    66       debug("notifyChanges notifying changes for " + aId);
    67       Services.obs.notifyObservers(null, "downloads-state-change-" + aId,
    68                                    JSON.stringify(this.downloads[aId]));
    69     } else {
    70       debug("notifyChanges failed for " + aId)
    71     }
    72   },
    74   _updateDownloadsArray: function(aDownloads) {
    75     this.downloads = [];
    76     // We actually have an array of downloads.
    77     aDownloads.forEach((aDownload) => {
    78       this.downloads[aDownload.id] = aDownload;
    79     });
    80   },
    82   receiveMessage: function(aMessage) {
    83     let download = aMessage.data;
    84     debug("message: " + aMessage.name);
    85     switch(aMessage.name) {
    86       case "Downloads:GetList:Return":
    87         this._updateDownloadsArray(download);
    89         if (!this.ready) {
    90           this.getListPromises.forEach(aPromise =>
    91                                        aPromise.resolve(this.downloads));
    92           this.getListPromises.length = 0;
    93         }
    94         this.ready = true;
    95         break;
    96       case "Downloads:ClearAllDone:Return":
    97         this._updateDownloadsArray(download);
    98         this.clearAllPromises.forEach(aPromise =>
    99                                       aPromise.resolve(this.downloads));
   100         this.clearAllPromises.length = 0;
   101         break;
   102       case "Downloads:Added":
   103         this.downloads[download.id] = download;
   104         this.notifyChanges(download.id);
   105         break;
   106       case "Downloads:Removed":
   107         if (this.downloads[download.id]) {
   108           this.downloads[download.id] = download;
   109           this.notifyChanges(download.id);
   110           delete this.downloads[download.id];
   111         }
   112         break;
   113       case "Downloads:Changed":
   114         // Only update properties that actually changed.
   115         let cached = this.downloads[download.id];
   116         if (!cached) {
   117           debug("No download found for " + download.id);
   118           return;
   119         }
   120         let props = ["totalBytes", "currentBytes", "url", "path", "state",
   121                      "contentType", "startTime"];
   122         let changed = false;
   124         props.forEach((aProp) => {
   125           if (download[aProp] && (download[aProp] != cached[aProp])) {
   126             cached[aProp] = download[aProp];
   127             changed = true;
   128           }
   129         });
   131         // Updating the error property. We always get a 'state' change as
   132         // well.
   133         cached.error = download.error;
   135         if (changed) {
   136           this.notifyChanges(download.id);
   137         }
   138         break;
   139       case "Downloads:Remove:Return":
   140       case "Downloads:Pause:Return":
   141       case "Downloads:Resume:Return":
   142         if (this.downloadPromises[download.promiseId]) {
   143           if (!download.error) {
   144             this.downloadPromises[download.promiseId].resolve(download);
   145           } else {
   146             this.downloadPromises[download.promiseId].reject(download);
   147           }
   148           delete this.downloadPromises[download.promiseId];
   149         }
   150         break;
   151     }
   152   },
   154   /**
   155     * Returns a promise that is resolved with the list of current downloads.
   156     */
   157   getDownloads: function() {
   158     debug("getDownloads()");
   159     let deferred = Promise.defer();
   160     if (this.ready) {
   161       debug("Returning existing list.");
   162       deferred.resolve(this.downloads);
   163     } else {
   164       this.getListPromises.push(deferred);
   165     }
   166     return deferred.promise;
   167   },
   169   /**
   170     * Returns a promise that is resolved with the list of current downloads.
   171     */
   172   clearAllDone: function() {
   173     debug("clearAllDone");
   174     let deferred = Promise.defer();
   175     this.clearAllPromises.push(deferred);
   176     cpmm.sendAsyncMessage("Downloads:ClearAllDone", {});
   177     return deferred.promise;
   178   },
   180   promiseId: function() {
   181     return this._promiseId++;
   182   },
   184   remove: function(aId) {
   185     debug("remove " + aId);
   186     let deferred = Promise.defer();
   187     let pId = this.promiseId();
   188     this.downloadPromises[pId] = deferred;
   189     cpmm.sendAsyncMessage("Downloads:Remove",
   190                           { id: aId, promiseId: pId });
   191     return deferred.promise;
   192   },
   194   pause: function(aId) {
   195     debug("pause " + aId);
   196     let deferred = Promise.defer();
   197     let pId = this.promiseId();
   198     this.downloadPromises[pId] = deferred;
   199     cpmm.sendAsyncMessage("Downloads:Pause",
   200                           { id: aId, promiseId: pId });
   201     return deferred.promise;
   202   },
   204   resume: function(aId) {
   205     debug("resume " + aId);
   206     let deferred = Promise.defer();
   207     let pId = this.promiseId();
   208     this.downloadPromises[pId] = deferred;
   209     cpmm.sendAsyncMessage("Downloads:Resume",
   210                           { id: aId, promiseId: pId });
   211     return deferred.promise;
   212   },
   214   observe: function(aSubject, aTopic, aData) {
   215     if (aTopic == "xpcom-shutdown") {
   216       ipcMessages.forEach((aMessage) => {
   217         cpmm.removeMessageListener(aMessage, this);
   218       });
   219     }
   220   }
   221 };
   223 DownloadsIPC.init();

mercurial