Backout 96eaa0f376ab (bug 961282) for smoketest regression.
authorFabrice Desré <fabrice@mozilla.com>
Fri, 21 Feb 2014 11:54:03 -0800
changeset 170361 a5758448882ae9ad86281c5bb139f6d4a29eba44
parent 170360 fd8317ed99900b33622318c90f1c24e7bcba9a56
child 170362 bb134fc596eb2040bcd961a5fd0463f45c870f27
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
bugs961282
milestone30.0a1
backs out96eaa0f376ab90b2efaee3cc326f805826abba17
Backout 96eaa0f376ab (bug 961282) for smoketest regression.
dom/apps/src/Webapps.jsm
toolkit/devtools/server/actors/webapps.js
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -105,24 +105,24 @@ XPCOMUtils.defineLazyGetter(this, "msgmg
 });
 
 XPCOMUtils.defineLazyGetter(this, "updateSvc", function() {
   return Cc["@mozilla.org/offlinecacheupdate-service;1"]
            .getService(Ci.nsIOfflineCacheUpdateService);
 });
 
 #ifdef MOZ_WIDGET_GONK
-  const DIRECTORY_KEY = "webappsDir";
+  const DIRECTORY_NAME = "webappsDir";
 #elifdef ANDROID
-  const DIRECTORY_KEY = "webappsDir";
+  const DIRECTORY_NAME = "webappsDir";
 #else
   // If we're executing in the context of the webapp runtime, the data files
   // are in a different directory (currently the Firefox profile that installed
   // the webapp); otherwise, they're in the current profile.
-  const DIRECTORY_KEY = WEBAPP_RUNTIME ? "WebappRegD" : "ProfD";
+  const DIRECTORY_NAME = WEBAPP_RUNTIME ? "WebappRegD" : "ProfD";
 #endif
 
 // We'll use this to identify privileged apps that have been preinstalled
 // For those apps we'll set
 // STORE_ID_PENDING_PREFIX + installOrigin
 // as the storeID. This ensures it's unique and can't be set from a legit
 // store even by error.
 const STORE_ID_PENDING_PREFIX = "#unknownID#";
@@ -156,30 +156,27 @@ this.DOMApplicationRegistry = {
 
     cpmm.addMessageListener("Activities:Register:OK", this);
 
     Services.obs.addObserver(this, "xpcom-shutdown", false);
     Services.obs.addObserver(this, "memory-pressure", false);
 
     AppDownloadManager.registerCancelFunction(this.cancelDownload.bind(this));
 
-    this.appsFile = OS.Path.join(Services.dirsvc.get(DIRECTORY_KEY, Ci.nsIFile).path,
-                                 "webapps", "webapps.json");
+    this.appsFile = FileUtils.getFile(DIRECTORY_NAME,
+                                      ["webapps", "webapps.json"], true).path;
 
     this.loadAndUpdateApps();
   },
 
   // loads the current registry, that could be empty on first run.
   loadCurrentRegistry: function() {
     return this._loadJSONAsync(this.appsFile).then((aData) => {
       if (!aData) {
-        // If _loadJSONAsync returns null, we're probably in the firstrun case
-        // so we may need to create the "webapps" directory.
-        return OS.File.makeDir(OS.Path.dirname(this.appsFile),
-                               { ignoreExisting: true });
+        return;
       }
 
       this.webapps = aData;
       let appDir = OS.Path.dirname(this.appsFile);
       for (let id in this.webapps) {
         let app = this.webapps[id];
         if (!app) {
           delete this.webapps[id];
@@ -405,23 +402,18 @@ this.DOMApplicationRegistry = {
     } else {
       isPackage = true;
       filesToMove = ["application.zip", "update.webapp"];
     }
 
     debug("Installing 3rd party app : " + aId +
           " from " + baseDir.path);
 
-    // We copy this app to DIRECTORY_KEY/$aId, and set the base path as needed.
-    let destDir = this._getAppDir(aId);
-    try {
-      destDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
-    } catch (ex if ex.result == Cr.NS_ERROR_FILE_ALREADY_EXISTS) {
-      // Ignore the exception if the directory already exists.
-    }
+    // We copy this app to DIRECTORY_NAME/$aId, and set the base path as needed.
+    let destDir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", aId], true, true);
 
     filesToMove.forEach(function(aFile) {
         let file = baseDir.clone();
         file.append(aFile);
         try {
           file.copyTo(destDir, aFile);
         } catch(e) {
           debug("Error: Failed to copy " + file.path + " to " + destDir.path);
@@ -1200,17 +1192,17 @@ this.DOMApplicationRegistry = {
       return;
     }
     this.children[aMsgName].forEach(function(mmRef) {
       mmRef.mm.sendAsyncMessage(aMsgName, aContent);
     });
   },
 
   _getAppDir: function(aId) {
-    return FileUtils.getDir(DIRECTORY_KEY, ["webapps", aId], false, true);
+    return FileUtils.getDir(DIRECTORY_NAME, ["webapps", aId], true, true);
   },
 
   _writeFile: function(aPath, aData) {
     debug("Saving " + aPath);
 
     return OS.File.writeAtomic(aPath,
                                new TextEncoder().encode(aData),
                                { tmpPath: aPath + ".tmp" })
@@ -1340,18 +1332,21 @@ this.DOMApplicationRegistry = {
 
     // An app download would only be triggered for two reasons: an app
     // update or while retrying to download a previously failed or canceled
     // instalation.
     app.retryingDownload = !isUpdate;
 
     // We need to get the update manifest here, not the webapp manifest.
     // If this is an update, the update manifest is staged.
-    let file = this._getAppDir(id);
-    file.append(isUpdate ? "staged-update.webapp" : "update.webapp");
+    let file = FileUtils.getFile(DIRECTORY_NAME,
+                                 ["webapps", id,
+                                  isUpdate ? "staged-update.webapp"
+                                           : "update.webapp"],
+                                 true);
 
     if (!file.exists()) {
       // This is a hosted app, let's check if it has an appcache
       // and download it.
       this._readManifests([{ id: id }]).then((aResults) => {
         let jsonManifest = aResults[0].manifest;
         let manifest = new ManifestHelper(jsonManifest, app.origin);
 
@@ -1431,23 +1426,23 @@ this.DOMApplicationRegistry = {
     let app = this.webapps[id];
     if (!app || (app && !app.readyToApplyDownload)) {
       return;
     }
 
     // We need to get the old manifest to unregister web activities.
     this.getManifestFor(aManifestURL).then((aOldManifest) => {
       // Move the application.zip and manifest.webapp files out of TmpD
-      let tmpDir = FileUtils.getDir("TmpD", ["webapps", id], false, true);
+      let tmpDir = FileUtils.getDir("TmpD", ["webapps", id], true, true);
       let manFile = tmpDir.clone();
       manFile.append("manifest.webapp");
       let appFile = tmpDir.clone();
       appFile.append("application.zip");
 
-      let dir = this._getAppDir(id);
+      let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
       appFile.moveTo(dir, "application.zip");
       manFile.moveTo(dir, "manifest.webapp");
 
       // Move the staged update manifest to a non staged one.
       let staged = dir.clone();
       staged.append("staged-update.webapp");
 
       // If we are applying after a restarted download, we have no
@@ -2200,24 +2195,26 @@ this.DOMApplicationRegistry = {
     xhr.addEventListener("error", (function() {
       sendError("NETWORK_ERROR");
     }).bind(this), false);
 
     xhr.send(null);
   },
 
   denyInstall: function(aData) {
-    Task.spawn(function*() {
-      let packageId = aData.app.packageId;
-      if (packageId) {
-        let dir = OS.Path.join(OS.Constants.Path.tmpDir, "webapps", packageId);
-        yield OS.File.removeDir(dir, { ignoreAbsent: true });
+    let packageId = aData.app.packageId;
+    if (packageId) {
+      let dir = FileUtils.getDir("TmpD", ["webapps", packageId],
+                                 true, true);
+      try {
+        dir.remove(true);
+      } catch(e) {
       }
-      aData.mm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
-    }).then(null, Cu.reportError);
+    }
+    aData.mm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
   },
 
   // This function is called after we called the onsuccess callback on the
   // content side. This let the webpage the opportunity to set event handlers
   // on the app before we start firing progress events.
   queuedDownload: {},
   queuedPackageDownload: {},
 
@@ -2309,23 +2306,24 @@ onInstallSuccessAck: function onInstallS
     appObject.csp = aManifest.csp || "";
     appObject.role = aManifest.role || "";
     appObject.installerAppId = aData.appId;
     appObject.installerIsBrowser = aData.isBrowser;
 
     return appObject;
   },
 
-  _writeManifestFile: function(aDir, aIsPackage, aJsonManifest) {
+  _writeManifestFile: function(aId, aIsPackage, aJsonManifest) {
     debug("_writeManifestFile");
 
     // For packaged apps, keep the update manifest distinct from the app manifest.
     let manifestName = aIsPackage ? "update.webapp" : "manifest.webapp";
 
-    let manFile = OS.Path.join(aDir, manifestName);
+    let dir = this._getAppDir(aId).path;
+    let manFile = OS.Path.join(dir, manifestName);
     this._writeFile(manFile, JSON.stringify(aJsonManifest));
   },
 
   confirmInstall: function(aData, aProfileDir, aInstallSuccessCallback) {
     debug("confirmInstall");
 
     let origin = Services.io.newURI(aData.app.origin, null, null);
     let id = this._appIdForManifestURL(aData.app.manifestURL);
@@ -2341,28 +2339,20 @@ onInstallSuccessAck: function onInstallS
       try {
         dir.remove(true);
       } catch(e) { }
     } else {
       id = this.makeAppId();
       localId = this._nextLocalId();
     }
 
-    // Create the app directory
-    let dir = this._getAppDir(id);
-    try {
-      dir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
-    } catch (ex if ex.result == Cr.NS_ERROR_FILE_ALREADY_EXISTS) {
-      // Ignore the exception if the directory already exists.
-    }
-
     let app = this._setupApp(aData, id);
 
     let jsonManifest = aData.isPackage ? app.updateManifest : app.manifest;
-    this._writeManifestFile(dir.path, aData.isPackage, jsonManifest);
+    this._writeManifestFile(id, aData.isPackage, jsonManifest);
 
     debug("app.origin: " + app.origin);
     let manifest = new ManifestHelper(jsonManifest, app.origin);
 
     let appObject = this._cloneApp(aData, app, manifest, id, localId);
 
     this.webapps[id] = appObject;
 
@@ -2472,24 +2462,21 @@ onInstallSuccessAck: function onInstallS
    * @param aId {Integer} the unique ID of the application
    * @param aManifest {Object} The manifest of the application
    */
   _onDownloadPackage: function(aNewApp, aInstallSuccessCallback,
                                [aId, aManifest]) {
     debug("_onDownloadPackage");
     // Success! Move the zip out of TmpD.
     let app = this.webapps[aId];
-
-    let tmpDir = FileUtils.getDir("TmpD", ["webapps", aId], false, true);
-    let zipFile = tmpDir.clone();
-    zipFile.append("application.zip");
-
+    let zipFile =
+      FileUtils.getFile("TmpD", ["webapps", aId, "application.zip"], true);
     let dir = this._getAppDir(aId);
     zipFile.moveTo(dir, "application.zip");
-
+    let tmpDir = FileUtils.getDir("TmpD", ["webapps", aId], true, true);
     try {
       tmpDir.remove(true);
     } catch(e) { }
 
     // Save the manifest
     let manFile = OS.Path.join(dir.path, "manifest.webapp");
     this._writeFile(manFile, JSON.stringify(aManifest));
     // Set state and fire events.
@@ -2572,17 +2559,17 @@ onInstallSuccessAck: function onInstallS
   _readManifests: function(aData) {
     return Task.spawn(function*() {
       for (let elem of aData) {
         let id = elem.id;
 
         if (!this._manifestCache[id]) {
           // the manifest file used to be named manifest.json, so fallback on this.
           let baseDir = this.webapps[id].basePath == this.getCoreAppsBasePath()
-                          ? "coreAppsDir" : DIRECTORY_KEY;
+                          ? "coreAppsDir" : DIRECTORY_NAME;
 
           let dir = FileUtils.getDir(baseDir, ["webapps", id], false, true);
 
           let fileNames = ["manifest.webapp", "update.webapp", "manifest.json"];
           for (let fileName of fileNames) {
             this._manifestCache[id] = yield this._loadJSONAsync(OS.Path.join(dir.path, fileName));
             if (this._manifestCache[id]) {
               break;
@@ -2700,17 +2687,17 @@ onInstallSuccessAck: function onInstallS
         } else {
           deferred.reject("INSUFFICIENT_STORAGE");
         }
       }
     } else {
       debug("No deviceStorage");
       // deviceStorage isn't available, so use FileUtils to find the size of
       // available storage.
-      let dir = FileUtils.getDir(DIRECTORY_KEY, ["webapps"], false, true);
+      let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps"], true, true);
       try {
         let sufficientStorage = this._checkDownloadSize(dir.diskSpaceAvailable,
                                                         aNewApp);
         if (sufficientStorage) {
           deferred.resolve();
         } else {
           deferred.reject("INSUFFICIENT_STORAGE");
         }
@@ -2957,19 +2944,20 @@ onInstallSuccessAck: function onInstallS
         app: aOldApp,
         manifestURL: aNewApp.manifestURL
       });
       this.broadcastMessage("Webapps:FireEvent", {
         manifestURL: aNewApp.manifestURL,
         eventType: ["downloadsuccess", "downloadapplied"]
       });
     });
-
-    let appDir = OS.Path.join(OS.Constants.Path.tmpDir, "webapps", aId);
-    OS.File.removeDir(appDir, { ignoreAbsent: true });
+    let file = FileUtils.getFile("TmpD", ["webapps", aId], false);
+    if (file && file.exists()) {
+      file.remove(true);
+    }
   },
 
   _openAndReadPackage: function(aZipFile, aOldApp, aNewApp, aIsLocalFileInstall,
                                 aIsUpdate, aManifest, aRequestChannel, aHash) {
     return Task.spawn((function*() {
       let zipReader, isSigned, newManifest;
 
       try {
@@ -3224,19 +3212,19 @@ onInstallSuccessAck: function onInstallS
         }
         aOldApp.origin = uri.prePath;
         // Update the registry.
         let oldId = aOldApp.id;
         aOldApp.id = newId;
         this.webapps[newId] = aOldApp;
         delete this.webapps[oldId];
         // Rename the directories where the files are installed.
-        [DIRECTORY_KEY, "TmpD"].forEach(function(aDir) {
-          let parent = FileUtils.getDir(aDir, ["webapps"], false, true);
-          let dir = FileUtils.getDir(aDir, ["webapps", oldId], false, true);
+        [DIRECTORY_NAME, "TmpD"].forEach(function(aDir) {
+          let parent = FileUtils.getDir(aDir, ["webapps"], true, true);
+          let dir = FileUtils.getDir(aDir, ["webapps", oldId], true, true);
           dir.moveTo(parent, newId);
         });
         // Signals that we need to swap the old id with the new app.
         this.broadcastMessage("Webapps:RemoveApp", { id: oldId });
         this.broadcastMessage("Webapps:AddApp", { id: newId,
                                                   app: aOldApp });
       }
     }
@@ -3303,17 +3291,17 @@ onInstallSuccessAck: function onInstallS
     } else if (isInstalled) {
       throw "WRONG_APP_STORE_ID";
     }
   },
 
   // Removes the directory we created, and sends an error to the DOM side.
   _revertDownloadPackage: function(aId, aOldApp, aNewApp, aIsUpdate, aError) {
     debug("Cleanup: " + aError + "\n" + aError.stack);
-    let dir = FileUtils.getDir("TmpD", ["webapps", aId], false, true);
+    let dir = FileUtils.getDir("TmpD", ["webapps", aId], true, true);
     try {
       dir.remove(true);
     } catch (e) { }
 
     // We avoid notifying the error to the DOM side if the app download
     // was cancelled via cancelDownload, which already sends its own
     // notification.
     if (aOldApp.isCanceling) {
--- a/toolkit/devtools/server/actors/webapps.js
+++ b/toolkit/devtools/server/actors/webapps.js
@@ -270,22 +270,16 @@ WebappsActor.prototype = {
     }
     function checkSideloading(aManifest) {
       return self._getAppType(aManifest.type);
     }
     function writeManifest(aAppType) {
       // Move manifest.webapp to the destination directory.
       // The destination directory for this app.
       let installDir = DOMApplicationRegistry._getAppDir(aId);
-      try {
-        installDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
-      } catch (ex if ex.result == Cr.NS_ERROR_FILE_ALREADY_EXISTS) {
-        // Ignore the exception if the directory already exists.
-      }
-
       if (aManifest) {
         let manFile = OS.Path.join(installDir.path, "manifest.webapp");
         return DOMApplicationRegistry._writeFile(manFile, JSON.stringify(aManifest)).then(() => {
           return aAppType;
         });
       } else {
         let manFile = aDir.clone();
         manFile.append("manifest.webapp");
@@ -395,22 +389,16 @@ WebappsActor.prototype = {
             }
             id = uri.prePath.substring(6);
           }
 
           // Only after security checks are made and after final app id is computed
           // we can move application.zip to the destination directory, and
           // extract manifest.webapp there.
           let installDir = DOMApplicationRegistry._getAppDir(id);
-          try {
-            installDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
-          } catch (ex if ex.result == Cr.NS_ERROR_FILE_ALREADY_EXISTS) {
-            // Ignore the exception if the directory already exists.
-          }
-
           let manFile = installDir.clone();
           manFile.append("manifest.webapp");
           zipReader.extract("manifest.webapp", manFile);
           zipReader.close();
           zipFile.moveTo(installDir, "application.zip");
 
           let origin = "app://" + id;
           let manifestURL = origin + "/manifest.webapp";