Backed out changeset 2767ff221c92 (bug 871445)
authorEd Morley <emorley@mozilla.com>
Wed, 02 Oct 2013 17:57:25 +0100
changeset 163536 ca1c692e20cbaa88053942075be712ae8bcd7f8b
parent 163535 89d239df9c87c5ba99dad2cb060c35fea70d04e7
child 163537 14984035bb134b7c2d0f26c4d95b73f18e60bdcd
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs871445
milestone27.0a1
backs out2767ff221c9240899735ad7667dfd50a8db6ede2
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 2767ff221c92 (bug 871445)
dom/apps/src/Webapps.jsm
dom/datastore/DataStore.jsm
dom/datastore/DataStoreChangeNotifier.jsm
dom/datastore/DataStoreDB.jsm
dom/datastore/DataStoreService.js
dom/datastore/DataStoreServiceInternal.jsm
dom/datastore/moz.build
dom/datastore/nsIDataStoreService.idl
dom/datastore/tests/test_app_install.html
dom/datastore/tests/test_arrays.html
dom/datastore/tests/test_basic.html
dom/datastore/tests/test_changes.html
dom/datastore/tests/test_oop.html
dom/datastore/tests/test_readonly.html
dom/datastore/tests/test_revision.html
testing/mochitest/manifest.webapp
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -279,17 +279,16 @@ this.DOMApplicationRegistry = {
   updateDataStoreForApp: function(aId) {
     if (!this.webapps[aId]) {
       return;
     }
 
     // Create or Update the DataStore for this app
     this._readManifests([{ id: aId }], (function(aResult) {
       this.updateDataStore(this.webapps[aId].localId,
-                           this.webapps[aId].origin,
                            this.webapps[aId].manifestURL,
                            aResult[0].manifest);
     }).bind(this));
   },
 
   updatePermissionsForApp: function updatePermissionsForApp(aId) {
     if (!this.webapps[aId]) {
       return;
@@ -526,63 +525,58 @@ this.DOMApplicationRegistry = {
         // At first run, install preloaded apps and set up their permissions.
         for (let id in this.webapps) {
           this.installPreinstalledApp(id);
           if (!this.webapps[id]) {
             continue;
           }
           this.updateOfflineCacheForApp(id);
           this.updatePermissionsForApp(id);
+          this.updateDataStoreForApp(id);
         }
         // Need to update the persisted list of apps since
         // installPreinstalledApp() removes the ones failing to install.
         this._saveApps();
       }
-
-      // DataStores must be initialized at startup.
-      for (let id in this.webapps) {
-        this.updateDataStoreForApp(id);
-      }
-
       this.registerAppsHandlers(runUpdate);
     }).bind(this);
 
     this.loadCurrentRegistry((function() {
 #ifdef MOZ_WIDGET_GONK
       // if first run, merge the system apps.
       if (runUpdate)
         this.installSystemApps(onAppsLoaded);
       else
         onAppsLoaded();
 #else
       onAppsLoaded();
 #endif
     }).bind(this));
   },
 
-  updateDataStore: function(aId, aOrigin, aManifestURL, aManifest) {
+  updateDataStore: function(aId, aManifestURL, aManifest) {
     if ('datastores-owned' in aManifest) {
       for (let name in aManifest['datastores-owned']) {
         let readonly = "access" in aManifest['datastores-owned'][name]
                          ? aManifest['datastores-owned'][name].access == 'readonly'
                          : false;
 
-        dataStoreService.installDataStore(aId, name, aOrigin, aManifestURL,
-                                          readonly);
+        dataStoreService.installDataStore(aId, name, aManifestURL, readonly);
       }
     }
 
     if ('datastores-access' in aManifest) {
       for (let name in aManifest['datastores-access']) {
         let readonly = ("readonly" in aManifest['datastores-access'][name]) &&
                        !aManifest['datastores-access'][name].readonly
                          ? false : true;
 
-        dataStoreService.installAccessDataStore(aId, name, aOrigin,
-                                                aManifestURL, readonly);
+        // The first release is always in readonly mode.
+        dataStoreService.installAccessDataStore(aId, name, aManifestURL,
+                                                /* readonly */ true);
       }
     }
   },
 
   // |aEntryPoint| is either the entry_point name or the null in which case we
   // use the root of the manifest.
   //
   // TODO Bug 908094 Refine _registerSystemMessagesForEntryPoint(...).
@@ -1435,18 +1429,17 @@ this.DOMApplicationRegistry = {
           this.updateAppHandlers(aOldManifest, aData, app);
           if (supportUseCurrentProfile()) {
             PermissionsInstaller.installPermissions(
               { manifest: aData,
                 origin: app.origin,
                 manifestURL: app.manifestURL },
               true);
           }
-          this.updateDataStore(this.webapps[id].localId, app.origin,
-                               app.manifestURL, aData);
+          this.updateDataStore(this.webapps[id].localId, app.manifestURL, aData);
           this.broadcastMessage("Webapps:PackageEvent",
                                 { type: "applied",
                                   manifestURL: app.manifestURL,
                                   app: app,
                                   manifest: aData });
         }).bind(this));
       }).bind(this));
     }).bind(this));
@@ -1642,18 +1635,17 @@ this.DOMApplicationRegistry = {
           // Update the permissions for this app.
           PermissionsInstaller.installPermissions({
             manifest: app.manifest,
             origin: app.origin,
             manifestURL: aData.manifestURL
           }, true);
         }
 
-        this.updateDataStore(this.webapps[id].localId, app.origin,
-                             app.manifestURL, app.manifest);
+        this.updateDataStore(this.webapps[id].localId, app.manifestURL, app.manifest);
 
         app.name = manifest.name;
         app.csp = manifest.csp || "";
         app.role = manifest.role || "";
         app.updateTime = Date.now();
       } else {
         manifest = new ManifestHelper(aOldManifest, app.origin);
       }
@@ -2145,18 +2137,18 @@ this.DOMApplicationRegistry = {
           if (supportUseCurrentProfile()) {
             // Update the permissions for this app.
             PermissionsInstaller.installPermissions({ manifest: aManifest,
                                                       origin: appObject.origin,
                                                       manifestURL: appObject.manifestURL },
                                                     true);
           }
 
-          this.updateDataStore(this.webapps[aId].localId, appObject.origin,
-                               appObject.manifestURL, aManifest);
+          this.updateDataStore(this.webapps[aId].localId, appObject.manifestURL,
+                               aManifest);
 
           debug("About to fire Webapps:PackageEvent 'installed'");
           this.broadcastMessage("Webapps:PackageEvent",
                                 { type: "installed",
                                   manifestURL: appObject.manifestURL,
                                   app: app,
                                   manifest: aManifest });
           if (installSuccessCallback) {
@@ -2251,18 +2243,18 @@ this.DOMApplicationRegistry = {
         PermissionsInstaller.installPermissions({ origin: appObject.origin,
                                                   manifestURL: appObject.manifestURL,
                                                   manifest: jsonManifest },
                                                 isReinstall, (function() {
           this.uninstall(aData, aData.mm);
         }).bind(this));
       }
 
-      this.updateDataStore(this.webapps[id].localId,  this.webapps[id].origin,
-                           this.webapps[id].manifestURL, jsonManifest);
+      this.updateDataStore(this.webapps[id].localId, this.webapps[id].manifestURL,
+                           jsonManifest);
     }
 
     ["installState", "downloadAvailable",
      "downloading", "downloadSize", "readyToApplyDownload"].forEach(function(aProp) {
       aData.app[aProp] = appObject[aProp];
      });
 
     if (manifest.appcache_path) {
--- a/dom/datastore/DataStore.jsm
+++ b/dom/datastore/DataStore.jsm
@@ -98,17 +98,17 @@ this.DataStore.prototype = {
     this._db = new DataStoreDB();
     this._db.init(aOwner, aName);
 
     let self = this;
     Services.obs.addObserver(function(aSubject, aTopic, aData) {
       let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
       if (wId == self._innerWindowID) {
         cpmm.removeMessageListener("DataStore:Changed:Return:OK", self);
-        self._db.close();
+        self._db.delete();
       }
     }, "inner-window-destroyed", false);
 
     let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                       .getInterface(Ci.nsIDOMWindowUtils);
     this._innerWindowID = util.currentInnerWindowID;
 
     cpmm.addMessageListener("DataStore:Changed:Return:OK", this);
@@ -273,28 +273,36 @@ this.DataStore.prototype = {
         aSuccessCb();
       }
     );
   },
 
   retrieveRevisionId: function(aSuccessCb) {
     let self = this;
     this._db.revisionTxn(
-      'readonly',
+      'readwrite',
       function(aTxn, aRevisionStore) {
         debug("RetrieveRevisionId transaction success");
 
         let request = aRevisionStore.openCursor(null, 'prev');
         request.onsuccess = function(aEvent) {
           let cursor = aEvent.target.result;
-          if (cursor) {
-            self._revisionId = cursor.value.revisionId;
+          if (!cursor) {
+            // If the revision doesn't exist, let's create the first one.
+            self.addRevision(aRevisionStore, 0, REVISION_VOID,
+              function(aRevisionId) {
+                self._revisionId = aRevisionId;
+                aSuccessCb();
+              }
+            );
+            return;
           }
 
-          aSuccessCb(self._revisionId);
+          self._revisionId = cursor.value.revisionId;
+          aSuccessCb();
         };
       }
     );
   },
 
   sendNotification: function(aId, aOperation, aRevisionId) {
     debug("SendNotification");
     if (aOperation != REVISION_VOID) {
@@ -462,17 +470,17 @@ this.DataStore.prototype = {
               // Initially we use maps, and then we convert them in array.
               let changes = {
                 revisionId: '',
                 addedIds: {},
                 updatedIds: {},
                 removedIds: {}
               };
 
-              let request = aStore.mozGetAll(IDBKeyRange.lowerBound(aInternalRevisionId, true));
+              let request = aStore.mozGetAll(self._window.IDBKeyRange.lowerBound(aInternalRevisionId, true));
               request.onsuccess = function(aEvent) {
                 for (let i = 0; i < aEvent.target.result.length; ++i) {
                   let data = aEvent.target.result[i];
 
                   switch (data.operation) {
                     case REVISION_ADDED:
                       changes.addedIds[data.objectId] = true;
                       break;
--- a/dom/datastore/DataStoreChangeNotifier.jsm
+++ b/dom/datastore/DataStoreChangeNotifier.jsm
@@ -7,19 +7,16 @@
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 this.EXPORTED_SYMBOLS = ["DataStoreChangeNotifier"];
 
 function debug(s) {
   //dump('DEBUG DataStoreChangeNotifier: ' + s + '\n');
 }
 
-// DataStoreServiceInternal should not be converted into a lazy getter as it
-// runs code during initialization.
-Cu.import('resource://gre/modules/DataStoreServiceInternal.jsm');
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
                                    "@mozilla.org/parentprocessmessagemanager;1",
                                    "nsIMessageBroadcaster");
 
 this.DataStoreChangeNotifier = {
--- a/dom/datastore/DataStoreDB.jsm
+++ b/dom/datastore/DataStoreDB.jsm
@@ -34,18 +34,18 @@ DataStoreDB.prototype = {
     debug('updateSchema');
     aDb.createObjectStore(DATASTOREDB_OBJECTSTORE_NAME, { autoIncrement: true });
     let store = aDb.createObjectStore(DATASTOREDB_REVISION,
                                       { autoIncrement: true,
                                         keyPath: 'internalRevisionId' });
     store.createIndex(DATASTOREDB_REVISION_INDEX, 'revisionId', { unique: true });
   },
 
-  init: function(aOwner, aName) {
-    let dbName = aName + '|' + aOwner;
+  init: function(aOrigin, aName) {
+    let dbName = aOrigin + '_' + aName;
     this.initDBHelper(dbName, DATASTOREDB_VERSION,
                       [DATASTOREDB_OBJECTSTORE_NAME, DATASTOREDB_REVISION]);
   },
 
   txn: function(aType, aCallback, aErrorCb) {
     debug('Transaction request');
     this.newTxn(
       aType,
--- a/dom/datastore/DataStoreService.js
+++ b/dom/datastore/DataStoreService.js
@@ -12,335 +12,134 @@ function debug(s) {
   // dump('DEBUG DataStoreService: ' + s + '\n');
 }
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/DataStore.jsm');
-Cu.import("resource://gre/modules/DataStoreDB.jsm");
 Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
                                    "@mozilla.org/childprocessmessagemanager;1",
                                    "nsIMessageSender");
 
 XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
                                    "@mozilla.org/parentprocessmessagemanager;1",
                                    "nsIMessageBroadcaster");
 
-XPCOMUtils.defineLazyServiceGetter(this, "permissionManager",
-                                   "@mozilla.org/permissionmanager;1",
-                                   "nsIPermissionManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "secMan",
-                                   "@mozilla.org/scriptsecuritymanager;1",
-                                   "nsIScriptSecurityManager");
-
 /* DataStoreService */
 
 const DATASTORESERVICE_CID = Components.ID('{d193d0e2-c677-4a7b-bb0a-19155b470f2e}');
-const REVISION_VOID = "void";
 
 function DataStoreService() {
   debug('DataStoreService Constructor');
 
-  this.inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
-                    .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
-
-  if (this.inParent) {
-    let obs = Services.obs;
-    if (!obs) {
-      debug("DataStore Error: observer-service is null!");
-      return;
-    }
-
-    obs.addObserver(this, 'webapps-clear-data', false);
+  let obs = Services.obs;
+  if (!obs) {
+    debug("DataStore Error: observer-service is null!");
+    return;
   }
 
-  let self = this;
-  cpmm.addMessageListener("datastore-first-revision-created",
-                          function(aMsg) { self.receiveMessage(aMsg); });
+  obs.addObserver(this, 'webapps-clear-data', false);
+
+  let inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
+                   .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
+  if (inParent) {
+    ppmm.addMessageListener("DataStore:Get", this);
+  }
 }
 
 DataStoreService.prototype = {
-  inParent: false,
-
   // Hash of DataStores
   stores: {},
   accessStores: {},
-  pendingRequests: {},
 
-  installDataStore: function(aAppId, aName, aOrigin, aOwner, aReadOnly) {
+  installDataStore: function(aAppId, aName, aOwner, aReadOnly) {
     debug('installDataStore - appId: ' + aAppId + ', aName: ' +
-          aName + ', aOrigin: ' + aOrigin + ', aOwner:' + aOwner +
-          ', aReadOnly: ' + aReadOnly);
-
-    this.checkIfInParent();
+          aName + ', aOwner:' + aOwner + ', aReadOnly: ' +
+          aReadOnly);
 
     if (aName in this.stores && aAppId in this.stores[aName]) {
       debug('This should not happen');
       return;
     }
 
     if (!(aName in this.stores)) {
       this.stores[aName] = {};
     }
 
-    // A DataStore is enabled when it has a first valid revision.
-    this.stores[aName][aAppId] = { origin: aOrigin, owner: aOwner,
-                                   readOnly: aReadOnly, enabled: false };
-
-    this.addPermissions(aAppId, aName, aOrigin, aOwner, aReadOnly);
-
-    this.createFirstRevisionId(aAppId, aName, aOwner);
+    this.stores[aName][aAppId] = { owner: aOwner, readOnly: aReadOnly };
   },
 
-  installAccessDataStore: function(aAppId, aName, aOrigin, aOwner, aReadOnly) {
-    debug('installAccessDataStore - appId: ' + aAppId + ', aName: ' +
-          aName + ', aOrigin: ' + aOrigin + ', aOwner:' + aOwner +
-          ', aReadOnly: ' + aReadOnly);
-
-    this.checkIfInParent();
+  installAccessDataStore: function(aAppId, aName, aOwner, aReadOnly) {
+    debug('installDataStore - appId: ' + aAppId + ', aName: ' +
+          aName + ', aOwner:' + aOwner + ', aReadOnly: ' +
+          aReadOnly);
 
     if (aName in this.accessStores && aAppId in this.accessStores[aName]) {
       debug('This should not happen');
       return;
     }
 
     if (!(aName in this.accessStores)) {
       this.accessStores[aName] = {};
     }
 
-    this.accessStores[aName][aAppId] = { origin: aOrigin, owner: aOwner,
-                                         readOnly: aReadOnly };
-    this.addAccessPermissions(aAppId, aName, aOrigin, aOwner, aReadOnly);
-  },
-
-  checkIfInParent: function() {
-    if (!this.inParent) {
-      throw "DataStore can execute this operation just in the parent process";
-    }
-  },
-
-  createFirstRevisionId: function(aAppId, aName, aOwner) {
-    debug("createFirstRevisionId database: " + aName);
-
-    let self = this;
-    let db = new DataStoreDB();
-    db.init(aOwner, aName);
-    db.revisionTxn(
-      'readwrite',
-      function(aTxn, aRevisionStore) {
-        debug("createFirstRevisionId - transaction success");
-
-        let request = aRevisionStore.openCursor(null, 'prev');
-        request.onsuccess = function(aEvent) {
-          let cursor = aEvent.target.result;
-          if (!cursor) {
-            // If the revision doesn't exist, let's create the first one.
-            db.addRevision(aRevisionStore, 0, REVISION_VOID, function() {
-              debug("First revision created.");
-              if (aName in self.stores && aAppId in self.stores[aName]) {
-                self.stores[aName][aAppId].enabled = true;
-                ppmm.broadcastAsyncMessage('datastore-first-revision-created',
-                                           { name: aName, owner: aOwner });
-              }
-            });
-          }
-        };
-      }
-    );
-  },
-
-  addPermissions: function(aAppId, aName, aOrigin, aOwner, aReadOnly) {
-    // When a new DataStore is installed, the permissions must be set for the
-    // owner app.
-    let permission = "indexedDB-chrome-" + aName + '|' + aOwner;
-    this.resetPermissions(aAppId, aOrigin, aOwner, permission, aReadOnly);
-
-    // For any app that wants to have access to this DataStore we add the
-    // permissions.
-    if (aName in this.accessStores) {
-      for (let appId in this.accessStores[aName]) {
-        // ReadOnly is decided by the owner first.
-        let readOnly = aReadOnly || this.accessStores[aName][appId].readOnly;
-        this.resetPermissions(appId, this.accessStores[aName][appId].origin,
-                              this.accessStores[aName][appId].owner,
-                              permission, readOnly);
-      }
-    }
-  },
-
-  addAccessPermissions: function(aAppId, aName, aOrigin, aOwner, aReadOnly) {
-    // When an app wants to have access to a DataStore, the permissions must be
-    // set.
-    if (!(aName in this.stores)) {
-      return;
-    }
-
-    for (let appId in this.stores[aName]) {
-      let permission = "indexedDB-chrome-" + aName + '|' + this.stores[aName][appId].owner;
-      // The ReadOnly is decied by the owenr first.
-      let readOnly = this.stores[aName][appId].readOnly || aReadOnly;
-      this.resetPermissions(aAppId, aOrigin, aOwner, permission, readOnly);
-    }
-  },
-
-  resetPermissions: function(aAppId, aOrigin, aOwner, aPermission, aReadOnly) {
-    debug("ResetPermissions - appId: " + aAppId + " - origin: " + aOrigin +
-          " - owner: " + aOwner + " - permissions: " + aPermission +
-          " - readOnly: " + aReadOnly);
-
-    let uri = Services.io.newURI(aOrigin, null, null);
-    let principal = secMan.getAppCodebasePrincipal(uri, aAppId, false);
-
-    let result = permissionManager.testExactPermissionFromPrincipal(principal,
-                                                                    aPermission + '-write');
-
-    if (aReadOnly && result == Ci.nsIPermissionManager.ALLOW_ACTION) {
-      debug("Write permission removed");
-      permissionManager.removeFromPrincipal(principal, aPermission + '-write');
-    } else if (!aReadOnly && result != Ci.nsIPermissionManager.ALLOW_ACTION) {
-      debug("Write permission added");
-      permissionManager.addFromPrincipal(principal, aPermission + '-write',
-                                         Ci.nsIPermissionManager.ALLOW_ACTION);
-    }
-
-    result = permissionManager.testExactPermissionFromPrincipal(principal,
-                                                                aPermission + '-read');
-    if (result != Ci.nsIPermissionManager.ALLOW_ACTION) {
-      debug("Read permission added");
-      permissionManager.addFromPrincipal(principal, aPermission + '-read',
-                                         Ci.nsIPermissionManager.ALLOW_ACTION);
-    }
-
-    result = permissionManager.testExactPermissionFromPrincipal(principal, aPermission);
-    if (result != Ci.nsIPermissionManager.ALLOW_ACTION) {
-      debug("Generic permission added");
-      permissionManager.addFromPrincipal(principal, aPermission,
-                                         Ci.nsIPermissionManager.ALLOW_ACTION);
-    }
+    this.accessStores[aName][aAppId] = { owner: aOwner, readOnly: aReadOnly };
   },
 
   getDataStores: function(aWindow, aName) {
     debug('getDataStores - aName: ' + aName);
 
-    let self = this;
+    // This method can be called in the child so we need to send a request to
+    // the parent and create DataStore object here.
+
     return new aWindow.Promise(function(resolve, reject) {
-      // If this request comes from the main process, we have access to the
-      // window, so we can skip the ipc communication.
-      if (self.inParent) {
-        let stores = self.getDataStoresInfo(aName, aWindow.document.nodePrincipal.appId);
-        self.getDataStoreCreate(aWindow, resolve, stores);
-      } else {
-        // This method can be called in the child so we need to send a request
-        // to the parent and create DataStore object here.
-        new DataStoreServiceChild(aWindow, aName, function(aStores) {
-          debug("DataStoreServiceChild callback!");
-          self.getDataStoreCreate(aWindow, resolve, aStores);
-        });
-      }
+      new DataStoreServiceChild(aWindow, aName, resolve);
     });
   },
 
-  getDataStoresInfo: function(aName, aAppId) {
-    debug('GetDataStoresInfo');
+  receiveMessage: function(aMessage) {
+    if (aMessage.name != 'DataStore:Get') {
+      return;
+    }
+
+    let msg = aMessage.data;
+
+    // This is a security issue and it will be fixed by Bug 916091
+    let appId = msg.appId;
 
     let results = [];
 
-    if (aName in this.stores) {
-      if (aAppId in this.stores[aName]) {
-        results.push({ name: aName,
-                       owner: this.stores[aName][aAppId].owner,
-                       readOnly: false,
-                       enabled: this.stores[aName][aAppId].enabled });
+    if (msg.name in this.stores) {
+      if (appId in this.stores[msg.name]) {
+        results.push({ store: this.stores[msg.name][appId],
+                       readOnly: false });
       }
 
-      for (var i in this.stores[aName]) {
-        if (i == aAppId) {
+      for (var i in this.stores[msg.name]) {
+        if (i == appId) {
           continue;
         }
 
-        let access = this.getDataStoreAccess(aName, aAppId);
+        let access = this.getDataStoreAccess(msg.name, appId);
         if (!access) {
           continue;
         }
 
-        let readOnly = this.stores[aName][i].readOnly || access.readOnly;
-        results.push({ name: aName,
-                       owner: this.stores[aName][i].owner,
-                       readOnly: readOnly,
-                       enabled: this.stores[aName][i].enabled });
-      }
-    }
-
-    return results;
-  },
-
-  getDataStoreCreate: function(aWindow, aResolve, aStores) {
-    debug("GetDataStoreCreate");
-
-    let results = [];
-
-    if (!aStores.length) {
-      aResolve(results);
-      return;
-    }
-
-    let pendingDataStores = [];
-
-    for (let i = 0; i < aStores.length; ++i) {
-      if (!aStores[i].enabled) {
-        pendingDataStores.push(aStores[i].owner);
+        let readOnly = this.stores[msg.name][i].readOnly || access.readOnly;
+        results.push({ store: this.stores[msg.name][i],
+                       readOnly: readOnly });
       }
     }
 
-    if (!pendingDataStores.length) {
-      this.getDataStoreResolve(aWindow, aResolve, aStores);
-      return;
-    }
-
-    if (!(aStores[0].name in this.pendingRequests)) {
-      this.pendingRequests[aStores[0].name] = [];
-    }
-
-    this.pendingRequests[aStores[0].name].push({ window: aWindow,
-                                                 resolve: aResolve,
-                                                 stores: aStores,
-                                                 pendingDataStores: pendingDataStores });
-  },
-
-  getDataStoreResolve: function(aWindow, aResolve, aStores) {
-    debug("GetDataStoreResolve");
-
-    let callbackPending = aStores.length;
-    let results = [];
-
-    if (!callbackPending) {
-      aResolve(results);
-      return;
-    }
-
-    for (let i = 0; i < aStores.length; ++i) {
-      let obj = new DataStore(aWindow, aStores[i].name,
-                              aStores[i].owner, aStores[i].readOnly);
-      let exposedObj = aWindow.DataStore._create(aWindow, obj);
-      results.push(exposedObj);
-
-      obj.retrieveRevisionId(
-        function() {
-          --callbackPending;
-          if (!callbackPending) {
-            aResolve(results);
-          }
-        }
-      );
-    }
+    msg.stores = results;
+    aMessage.target.sendAsyncMessage("DataStore:Get:Return", msg);
   },
 
   getDataStoreAccess: function(aName, aAppId) {
     if (!(aName in this.accessStores) ||
         !(aAppId in this.accessStores[aName])) {
       return null;
     }
 
@@ -358,98 +157,84 @@ DataStoreService.prototype = {
 
     // DataStore is explosed to apps, not browser content.
     if (params.browserOnly) {
       return;
     }
 
     for (let key in this.stores) {
       if (params.appId in this.stores[key]) {
-        this.deleteDatabase(key, this.stores[key][params.appId].owner);
         delete this.stores[key][params.appId];
       }
 
       if (!this.stores[key].length) {
         delete this.stores[key];
       }
     }
   },
 
-  deleteDatabase: function(aName, aOwner) {
-    debug("delete database: " + aName);
-
-    let db = new DataStoreDB();
-    db.init(aOwner, aName);
-    db.delete();
-  },
-
-  receiveMessage: function(aMsg) {
-    debug("receiveMessage");
-    let data = aMsg.json;
-
-    if (!(data.name in this.pendingRequests)) {
-      return;
-    }
-
-    for (let i = 0; i < this.pendingRequests[data.name].length;) {
-      let pos = this.pendingRequests[data.name][i].pendingDataStores.indexOf(data.owner);
-      if (pos != -1) {
-        this.pendingRequests[data.name][i].pendingDataStores.splice(pos, 1);
-        if (!this.pendingRequests[data.name][i].pendingDataStores.length) {
-          this.getDataStoreResolve(this.pendingRequests[data.name][i].window,
-                                   this.pendingRequests[data.name][i].resolve,
-                                   this.pendingRequests[data.name][i].stores);
-          this.pendingRequests[data.name].splice(i, 1);
-          continue;
-        }
-      }
-
-      ++i;
-    }
-
-    if (!this.pendingRequests[data.name].length) {
-      delete this.pendingRequests[data.name];
-    }
-  },
-
   classID : DATASTORESERVICE_CID,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataStoreService,
                                          Ci.nsIObserver]),
   classInfo: XPCOMUtils.generateCI({
     classID: DATASTORESERVICE_CID,
     contractID: '@mozilla.org/datastore-service;1',
     interfaces: [Ci.nsIDataStoreService, Ci.nsIObserver],
     flags: Ci.nsIClassInfo.SINGLETON
   })
 };
 
 /* DataStoreServiceChild */
 
-function DataStoreServiceChild(aWindow, aName, aCallback) {
+function DataStoreServiceChild(aWindow, aName, aResolve) {
   debug("DataStoreServiceChild created");
-  this.init(aWindow, aName, aCallback);
+  this.init(aWindow, aName, aResolve);
 }
 
 DataStoreServiceChild.prototype = {
   __proto__: DOMRequestIpcHelper.prototype,
 
-  init: function(aWindow, aName, aCallback) {
-    debug("DataStoreServiceChild init");
-    this._callback = aCallback;
+  init: function(aWindow, aName, aResolve) {
+    this._window = aWindow;
+    this._name = aName;
+    this._resolve = aResolve;
 
     this.initDOMRequestHelper(aWindow, [ "DataStore:Get:Return" ]);
 
     // This is a security issue and it will be fixed by Bug 916091
     cpmm.sendAsyncMessage("DataStore:Get",
                           { name: aName, appId: aWindow.document.nodePrincipal.appId });
   },
 
   receiveMessage: function(aMessage) {
-    debug("DataStoreServiceChild receiveMessage");
     if (aMessage.name != 'DataStore:Get:Return') {
       return;
     }
+    let msg = aMessage.data;
+    let self = this;
 
-    this._callback(aMessage.data.stores);
+    let callbackPending = msg.stores.length;
+    let results = [];
+
+    if (!callbackPending) {
+      this._resolve(results);
+      return;
+    }
+
+    for (let i = 0; i < msg.stores.length; ++i) {
+      let obj = new DataStore(this._window, this._name,
+                              msg.stores[i].owner, msg.stores[i].readOnly);
+      let exposedObj = this._window.DataStore._create(this._window, obj);
+      results.push(exposedObj);
+
+      obj.retrieveRevisionId(
+        function() {
+          --callbackPending;
+          if (!callbackPending) {
+            self._resolve(results);
+          }
+        }
+      );
+    }
   }
 }
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataStoreService]);
deleted file mode 100644
--- a/dom/datastore/DataStoreServiceInternal.jsm
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 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 {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-this.EXPORTED_SYMBOLS = ["DataStoreServiceInternal"];
-
-function debug(s) {
-  // dump('DEBUG DataStoreServiceInternal: ' + s + '\n');
-}
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
-                                   "@mozilla.org/parentprocessmessagemanager;1",
-                                   "nsIMessageBroadcaster");
-
-XPCOMUtils.defineLazyServiceGetter(this, "dataStoreService",
-                                   "@mozilla.org/datastore-service;1",
-                                   "nsIDataStoreService");
-
-this.DataStoreServiceInternal = {
-  init: function() {
-    debug("init");
-
-    let inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
-                      .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
-    if (inParent) {
-      ppmm.addMessageListener("DataStore:Get", this);
-    }
-  },
-
-  receiveMessage: function(aMessage) {
-    debug("receiveMessage");
-
-    if (aMessage.name != 'DataStore:Get') {
-      return;
-    }
-
-    let msg = aMessage.data;
-
-    // This is a security issue and it will be fixed by Bug 916091
-    msg.stores = dataStoreService.getDataStoresInfo(msg.name, msg.appId);
-    aMessage.target.sendAsyncMessage("DataStore:Get:Return", msg);
-  }
-}
-
-DataStoreServiceInternal.init();
--- a/dom/datastore/moz.build
+++ b/dom/datastore/moz.build
@@ -18,10 +18,9 @@ EXTRA_COMPONENTS += [
     'DataStore.manifest',
     'DataStoreService.js',
 ]
 
 EXTRA_JS_MODULES += [
     'DataStore.jsm',
     'DataStoreChangeNotifier.jsm',
     'DataStoreDB.jsm',
-    'DataStoreServiceInternal.jsm',
 ]
--- a/dom/datastore/nsIDataStoreService.idl
+++ b/dom/datastore/nsIDataStoreService.idl
@@ -2,34 +2,24 @@
 /* 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/. */
 
 #include "nsISupports.idl"
 
 interface nsIDOMWindow;
 
-[scriptable, uuid(bd02d09c-41ab-47b7-9319-57aa8e5059b0)]
+[scriptable, uuid(d193d0e2-c677-4a7b-bb0a-19155b470f2e)]
 interface nsIDataStoreService : nsISupports
 {
   void installDataStore(in unsigned long appId,
                         in DOMString name,
-                        in DOMString originURL,
                         in DOMString manifestURL,
                         in boolean readOnly);
 
   void installAccessDataStore(in unsigned long appId,
                               in DOMString name,
-                              in DOMString originURL,
                               in DOMString manifestURL,
                               in boolean readOnly);
 
   nsISupports getDataStores(in nsIDOMWindow window,
                             in DOMString name);
-
-  // This is an array of objects composed by:
-  // - readOnly: boolean
-  // - name: DOMString
-  // - owner: DOMString
-  // - enabled: true/false - true if this dataStore is ready to be used.
-  jsval getDataStoresInfo(in DOMString name,
-                          in unsigned long appId);
 };
--- a/dom/datastore/tests/test_app_install.html
+++ b/dom/datastore/tests/test_app_install.html
@@ -5,33 +5,30 @@
   <title>Test for DataStore - install/uninstall apps</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <div id="container"></div>
   <script type="application/javascript;version=1.7">
 
-  if (SpecialPowers.isMainProcess()) {
-    SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
-  }
+ SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
 
   SimpleTest.waitForExplicitFinish();
 
   var gBaseURL = 'http://test/tests/dom/datastore/tests/';
   var gHostedManifestURL = gBaseURL + 'file_app.sjs?testToken=file_app_install.html';
   var gGenerator = runTest();
 
   SpecialPowers.pushPermissions(
     [{ "type": "browser", "allow": 1, "context": document },
      { "type": "embed-apps", "allow": 1, "context": document },
      { "type": "webapps-manage", "allow": 1, "context": document }],
     function() {
-      SpecialPowers.pushPrefEnv({"set": [["dom.datastore.enabled", true],
-                                         ["dom.promise.enabled", true]]}, function() {
+      SpecialPowers.pushPrefEnv({"set": [["dom.datastore.enabled", true]]}, function() {
         gGenerator.next(); });
     });
 
   function continueTest() {
     try { gGenerator.next(); }
     catch(e) { dump("Got exception: " + e + "\n"); }
   }
 
@@ -44,17 +41,16 @@
     ok("getDataStores" in navigator, "getDataStores exists");
     is(typeof navigator.getDataStores, "function", "getDataStores exists and it's a function");
     navigator.getDataStores('foo').then(function(stores) {
       is(stores.length, 0, "getDataStores('foo') returns 0 elements");
       continueTest();
     }, cbError);
     yield undefined;
 
-    SpecialPowers.setAllAppsLaunchable(true);
     SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);
 
     SpecialPowers.autoConfirmAppInstall(continueTest);
     yield undefined;
 
     var request = navigator.mozApps.install(gHostedManifestURL);
     request.onerror = cbError;
     request.onsuccess = continueTest;
--- a/dom/datastore/tests/test_arrays.html
+++ b/dom/datastore/tests/test_arrays.html
@@ -79,17 +79,16 @@
       SpecialPowers.pushPrefEnv({"set": [["dom.promise.enabled", true]]}, runTest);
     },
 
     function() {
       SpecialPowers.pushPrefEnv({"set": [["dom.datastore.enabled", true]]}, runTest);
     },
 
     function() {
-      SpecialPowers.setAllAppsLaunchable(true);
       SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);
       runTest();
     },
 
     // No confirmation needed when an app is installed
     function() {
       SpecialPowers.autoConfirmAppInstall(runTest);
     },
@@ -113,17 +112,14 @@
     var test = tests.shift();
     test();
   }
 
   function finish() {
     SimpleTest.finish();
   }
 
-  if (SpecialPowers.isMainProcess()) {
-    SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
-  }
-
+  SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
   SimpleTest.waitForExplicitFinish();
   runTest();
   </script>
 </body>
 </html>
--- a/dom/datastore/tests/test_basic.html
+++ b/dom/datastore/tests/test_basic.html
@@ -79,17 +79,16 @@
       SpecialPowers.pushPrefEnv({"set": [["dom.promise.enabled", true]]}, runTest);
     },
 
     function() {
       SpecialPowers.pushPrefEnv({"set": [["dom.datastore.enabled", true]]}, runTest);
     },
 
     function() {
-      SpecialPowers.setAllAppsLaunchable(true);
       SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);
       runTest();
     },
 
     // No confirmation needed when an app is installed
     function() {
       SpecialPowers.autoConfirmAppInstall(runTest);
     },
@@ -113,17 +112,14 @@
     var test = tests.shift();
     test();
   }
 
   function finish() {
     SimpleTest.finish();
   }
 
-  if (SpecialPowers.isMainProcess()) {
-    SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
-  }
-
+  SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
   SimpleTest.waitForExplicitFinish();
   runTest();
   </script>
 </body>
 </html>
--- a/dom/datastore/tests/test_changes.html
+++ b/dom/datastore/tests/test_changes.html
@@ -124,17 +124,16 @@
     },
 
     function() {
       SpecialPowers.pushPrefEnv({"set": [["dom.datastore.enabled", true]]}, runTest);
     },
 
     // Enabling mozBrowser
     function() {
-      SpecialPowers.setAllAppsLaunchable(true);
       SpecialPowers.pushPrefEnv({"set": [["dom.mozBrowserFramesEnabled", true]]}, runTest);
     },
 
     // No confirmation needed when an app is installed
     function() {
       SpecialPowers.autoConfirmAppInstall(runTest);
     },
 
@@ -166,20 +165,17 @@
     var test = tests.shift();
     test();
   }
 
   function finish() {
     SimpleTest.finish();
   }
 
-  if (SpecialPowers.isMainProcess()) {
-    SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
-  }
-
+  SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
   SimpleTest.waitForExplicitFinish();
   runTest();
   </script>
 </pre>
 </body>
 </html>
 
 
--- a/dom/datastore/tests/test_oop.html
+++ b/dom/datastore/tests/test_oop.html
@@ -83,17 +83,16 @@
       SpecialPowers.pushPrefEnv({"set": [["dom.datastore.enabled", true]]}, runTest);
     },
 
     function() {
       SpecialPowers.pushPrefEnv({"set": [["dom.ipc.browser_frames.oop_by_default", true]]}, runTest);
     },
 
     function() {
-      SpecialPowers.setAllAppsLaunchable(true);
       SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);
       runTest();
     },
 
     // No confirmation needed when an app is installed
     function() {
       SpecialPowers.autoConfirmAppInstall(runTest);
     },
@@ -117,17 +116,14 @@
     var test = tests.shift();
     test();
   }
 
   function finish() {
     SimpleTest.finish();
   }
 
-  if (SpecialPowers.isMainProcess()) {
-    SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
-  }
-
+  SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
   SimpleTest.waitForExplicitFinish();
   runTest();
   </script>
 </body>
 </html>
--- a/dom/datastore/tests/test_readonly.html
+++ b/dom/datastore/tests/test_readonly.html
@@ -25,17 +25,16 @@
   }
 
   function cbError() {
     ok(false, "Error callback invoked");
     finish();
   }
 
   function runTest() {
-    SpecialPowers.setAllAppsLaunchable(true);
     SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);
 
     SpecialPowers.autoConfirmAppInstall(continueTest);
     yield undefined;
 
     var request = navigator.mozApps.install(gHostedManifestURL);
     request.onerror = cbError;
     request.onsuccess = continueTest;
@@ -90,18 +89,16 @@
     domParent.appendChild(ifr);
   }
 
   function finish() {
     SpecialPowers.clearUserPref("dom.mozBrowserFramesEnabled");
     SimpleTest.finish();
   }
 
-  if (SpecialPowers.isMainProcess()) {
-    SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
-  }
-
+  SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
   SimpleTest.waitForExplicitFinish();
-  SpecialPowers.pushPrefEnv({"set": [["dom.promise.enabled", true],
-                                     ["dom.datastore.enabled", true]]}, runTest);
+  SpecialPowers.pushPrefEnv({"set": [["dom.promise.enabled", true]]}, function() {
+    SpecialPowers.pushPrefEnv({"set": [["dom.datastore.enabled", true]]}, runTest);
+  });
   </script>
 </body>
 </html>
--- a/dom/datastore/tests/test_revision.html
+++ b/dom/datastore/tests/test_revision.html
@@ -89,17 +89,16 @@
     },
 
     function() {
       SpecialPowers.pushPrefEnv({"set": [["dom.datastore.enabled", true]]}, runTest);
     },
 
     // Enabling mozBrowser
     function() {
-      SpecialPowers.setAllAppsLaunchable(true);
       SpecialPowers.pushPrefEnv({"set": [["dom.mozBrowserFramesEnabled", true]]}, runTest);
     },
 
     // No confirmation needed when an app is installed
     function() {
       SpecialPowers.autoConfirmAppInstall(runTest);
     },
 
@@ -122,19 +121,16 @@
     var test = tests.shift();
     test();
   }
 
   function finish() {
     SimpleTest.finish();
   }
 
-  if (SpecialPowers.isMainProcess()) {
-    SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
-  }
-
+  SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
   SimpleTest.waitForExplicitFinish();
   runTest();
   </script>
 </pre>
 </body>
 </html>
 
--- a/testing/mochitest/manifest.webapp
+++ b/testing/mochitest/manifest.webapp
@@ -30,14 +30,10 @@
     "systemXHR":{}
   },
   "locales": {
     "en-US": {
       "name": "Mochitest",
       "description": "Mochitests"
     }
   },
-  "datastores-access" : {
-    "foo" : { "readonly": false },
-    "bar" : { "readonly": false }
-  },
   "default_locale": "en-US"
 }