Bug 1034730 - Test installing app with appcache. r=myk
authorMarco Castelluccio <mar.castelluccio@studenti.unina.it>
Fri, 11 Jul 2014 01:53:48 +0200
changeset 193507 3db5124bd6c04bd440227f81a78139dad55f3e21
parent 193506 c7df28f9f5458ea436a6acff5eacbc5429c073a2
child 193508 96aa9d33a1f515363915c28ca0a3afc61c163747
push id27123
push userryanvm@gmail.com
push dateFri, 11 Jul 2014 20:35:05 +0000
treeherdermozilla-central@84bd8d9f4256 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmyk
bugs1034730
milestone33.0a1
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
Bug 1034730 - Test installing app with appcache. r=myk
toolkit/webapps/tests/chrome.ini
toolkit/webapps/tests/data/appcached_app/index.html
toolkit/webapps/tests/data/appcached_app/manifest.appcache
toolkit/webapps/tests/data/appcached_app/manifest.appcache^headers^
toolkit/webapps/tests/data/appcached_app/manifest.webapp
toolkit/webapps/tests/data/appcached_app/manifest.webapp^headers^
toolkit/webapps/tests/head.js
toolkit/webapps/tests/test_install_appcache.xul
--- a/toolkit/webapps/tests/chrome.ini
+++ b/toolkit/webapps/tests/chrome.ini
@@ -2,16 +2,18 @@
 skip-if = os == "mac" && os_version == "10.6" # see bug 993690
 support-files =
   head.js
   app.sjs
   data/*
 
 [test_custom_origin.xul]
 skip-if = asan
+[test_install_appcache.xul]
+skip-if = asan
 [test_hosted.xul]
 [test_packaged.xul]
 [test_hosted_launch.xul]
 skip-if = asan
 [test_hosted_launch_no_registry.xul]
 skip-if = asan
 [test_packaged_launch.xul]
 skip-if = asan
new file mode 100644
--- /dev/null
+++ b/toolkit/webapps/tests/data/appcached_app/index.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html manifest="manifest.appcache">
+<head>
+<title>Test app</title>
+</head>
+<body>
+<script type="application/javascript">
+window.applicationCache.addEventListener('noupdate', function(aEvent) {
+  var iframe = document.getElementById('ifr');
+  iframe.src = "http://127.0.0.1:8888/chrome/toolkit/webapps/tests/app.sjs?appreq";
+}, false);
+</script>
+<iframe id="ifr"></iframe>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/toolkit/webapps/tests/data/appcached_app/manifest.appcache
@@ -0,0 +1,3 @@
+CACHE MANIFEST
+# Version 1
+/chrome/toolkit/webapps/tests/data/appcached_app/index.html
new file mode 100644
--- /dev/null
+++ b/toolkit/webapps/tests/data/appcached_app/manifest.appcache^headers^
@@ -0,0 +1,1 @@
+Content-Type: text/cache-manifest
new file mode 100644
--- /dev/null
+++ b/toolkit/webapps/tests/data/appcached_app/manifest.webapp
@@ -0,0 +1,5 @@
+{
+  "name": "App using AppCache",
+  "launch_path": "/chrome/toolkit/webapps/tests/data/appcached_app/index.html",
+  "appcache_path": "/chrome/toolkit/webapps/tests/data/appcached_app/manifest.appcache"
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/webapps/tests/data/appcached_app/manifest.webapp^headers^
@@ -0,0 +1,1 @@
+Content-Type: application/x-web-app-manifest+json
--- a/toolkit/webapps/tests/head.js
+++ b/toolkit/webapps/tests/head.js
@@ -77,16 +77,40 @@ function dirContainsOnly(dir, expectedFi
         ret = false;
       }
     }
 
     return ret;
   });
 }
 
+let dirSize = Task.async(function*(aDir) {
+  let iterator = new OS.File.DirectoryIterator(aDir);
+
+  let entries;
+  try {
+    entries = yield iterator.nextBatch();
+  } finally {
+    iterator.close();
+  }
+
+  let size = 0;
+
+  for each (let entry in entries) {
+    if (entry.isDir) {
+      size += yield dirSize(entry.path);
+    } else {
+      let stat = yield OS.File.stat(entry.path);
+      size += stat.size;
+    }
+  }
+
+  return size;
+});
+
 function wait(time) {
   let deferred = Promise.defer();
 
   setTimeout(function() {
     deferred.resolve();
   }, time);
 
   return deferred.promise;
@@ -117,32 +141,34 @@ function setDryRunPref() {
 }
 
 function TestAppInfo(aApp, aIsPackaged) {
   this.appProcess = Cc["@mozilla.org/process/util;1"].
                     createInstance(Ci.nsIProcess);
 
   this.isPackaged = aIsPackaged;
 
+  this.uniqueName = WebappOSUtils.getUniqueName(aApp);
+
   if (LINUX) {
     this.installPath = OS.Path.join(OS.Constants.Path.homeDir,
-                                    "." + WebappOSUtils.getUniqueName(aApp));
+                                    "." + this.uniqueName);
     this.exePath = OS.Path.join(this.installPath, "webapprt-stub");
 
     this.iconFile = OS.Path.join(this.installPath, "icon.png");
 
     let xdg_data_home = Cc["@mozilla.org/process/environment;1"].
                         getService(Ci.nsIEnvironment).
                         get("XDG_DATA_HOME");
     if (!xdg_data_home) {
       xdg_data_home = OS.Path.join(OS.Constants.Path.homeDir, ".local", "share");
     }
 
     let desktopINI = OS.Path.join(xdg_data_home, "applications",
-                                  "owa-" + WebappOSUtils.getUniqueName(aApp) + ".desktop");
+                                  "owa-" + this.uniqueName + ".desktop");
 
     this.installedFiles = [
       OS.Path.join(this.installPath, "webapp.json"),
       OS.Path.join(this.installPath, "webapp.ini"),
       this.iconFile,
       this.exePath,
       desktopINI,
     ];
@@ -160,34 +186,36 @@ function TestAppInfo(aApp, aIsPackaged) 
 
     if (this.isPackaged) {
       let appZipPath = OS.Path.join(this.installPath, "application.zip");
       this.installedFiles.push(appZipPath);
       this.tempUpdatedFiles.push(appZipPath);
       this.updatedFiles.push(appZipPath);
     }
 
-    this.profilesIni = OS.Path.join(this.installPath, "profiles.ini");
+    this.profileRoot = this.installPath;
+    this.cacheRoot = OS.Path.join(OS.Constants.Path.homeDir, ".cache",
+                                  this.uniqueName);
 
     this.cleanup = Task.async(function*() {
       if (this.appProcess && this.appProcess.isRunning) {
         this.appProcess.kill();
       }
 
-      if (this.profileDir) {
-        yield OS.File.removeDir(this.profileDir.parent.path, { ignoreAbsent: true });
-      }
+      yield OS.File.removeDir(this.cacheRoot, { ignoreAbsent: true });
+
+      yield OS.File.removeDir(this.profileRoot, { ignoreAbsent: true });
 
       yield OS.File.removeDir(this.installPath, { ignoreAbsent: true });
 
       yield OS.File.remove(desktopINI, { ignoreAbsent: true });
     });
   } else if (WIN) {
     this.installPath = OS.Path.join(OS.Constants.Path.winAppDataDir,
-                                    WebappOSUtils.getUniqueName(aApp));
+                                    this.uniqueName);
     this.exePath = OS.Path.join(this.installPath, aApp.name + ".exe");
 
     this.iconFile = OS.Path.join(this.installPath, "chrome", "icons", "default", "default.ico");
 
     let desktopShortcut = OS.Path.join(OS.Constants.Path.desktopDir,
                                        aApp.name + ".lnk");
     let startMenuShortcut = OS.Path.join(OS.Constants.Path.winStartMenuProgsDir,
                                          aApp.name + ".lnk");
@@ -223,46 +251,48 @@ function TestAppInfo(aApp, aIsPackaged) 
 
     if (this.isPackaged) {
       let appZipPath = OS.Path.join(this.installPath, "application.zip");
       this.installedFiles.push(appZipPath);
       this.tempUpdatedFiles.push(appZipPath);
       this.updatedFiles.push(appZipPath);
     }
 
-    this.profilesIni = OS.Path.join(this.installPath, "profiles.ini");
+    this.profileRoot = this.installPath;
+    this.cacheRoot = OS.Path.join(Services.dirsvc.get("LocalAppData", Ci.nsIFile).path,
+                                  this.uniqueName);
 
     this.cleanup = Task.async(function*() {
       if (this.appProcess && this.appProcess.isRunning) {
         this.appProcess.kill();
       }
 
       let uninstallKey;
       try {
         uninstallKey = Cc["@mozilla.org/windows-registry-key;1"].
                        createInstance(Ci.nsIWindowsRegKey);
         uninstallKey.open(uninstallKey.ROOT_KEY_CURRENT_USER,
                           "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
                           uninstallKey.ACCESS_WRITE);
-        if (uninstallKey.hasChild(WebappOSUtils.getUniqueName(aApp))) {
-          uninstallKey.removeChild(WebappOSUtils.getUniqueName(aApp));
+        if (uninstallKey.hasChild(this.uniqueName)) {
+          uninstallKey.removeChild(this.uniqueName);
         }
       } catch (e) {
       } finally {
         if (uninstallKey) {
           uninstallKey.close();
         }
       }
 
       let removed = false;
       do {
         try {
-          if (this.profileDir) {
-            yield OS.File.removeDir(this.profileDir.parent.parent.path, { ignoreAbsent: true });
-          }
+          yield OS.File.removeDir(this.cacheRoot, { ignoreAbsent: true });
+
+          yield OS.File.removeDir(this.profileRoot, { ignoreAbsent: true });
 
           yield OS.File.removeDir(this.installPath, { ignoreAbsent: true });
 
           yield OS.File.remove(desktopShortcut, { ignoreAbsent: true });
           yield OS.File.remove(startMenuShortcut, { ignoreAbsent: true });
 
           removed = true;
         } catch (ex if ex instanceof OS.File.Error &&
@@ -279,17 +309,17 @@ function TestAppInfo(aApp, aIsPackaged) 
                                     "Applications",
                                     aApp.name + ".app");
     this.exePath = OS.Path.join(this.installPath, "Contents", "MacOS", "webapprt");
 
     this.iconFile = OS.Path.join(this.installPath, "Contents", "Resources", "appicon.icns");
 
     let appProfileDir = OS.Path.join(OS.Constants.Path.macUserLibDir,
                                      "Application Support",
-                                     WebappOSUtils.getUniqueName(aApp));
+                                     this.uniqueName);
 
     this.installedFiles = [
       OS.Path.join(this.installPath, "Contents", "Info.plist"),
       OS.Path.join(this.installPath, "Contents", "MacOS", "webapp.ini"),
       OS.Path.join(appProfileDir, "webapp.json"),
       this.iconFile,
       this.exePath,
     ];
@@ -308,36 +338,85 @@ function TestAppInfo(aApp, aIsPackaged) 
 
     if (this.isPackaged) {
       let appZipPath = OS.Path.join(this.installPath, "Contents", "Resources", "application.zip");
       this.installedFiles.push(appZipPath);
       this.tempUpdatedFiles.push(appZipPath);
       this.updatedFiles.push(appZipPath);
     }
 
-    this.profilesIni = OS.Path.join(appProfileDir, "profiles.ini");
+    this.profileRoot = appProfileDir;
+    this.cacheRoot = OS.Path.join(OS.Constants.Path.macUserLibDir, "Caches",
+                                  this.uniqueName);
 
     this.cleanup = Task.async(function*() {
       if (this.appProcess && this.appProcess.isRunning) {
         this.appProcess.kill();
       }
 
-      if (this.profileDir) {
-        yield OS.File.removeDir(this.profileDir.parent.path, { ignoreAbsent: true });
-      }
+      yield OS.File.removeDir(this.cacheRoot, { ignoreAbsent: true });
+
+      yield OS.File.removeDir(this.profileRoot, { ignoreAbsent: true });
 
       if (this.trashDir) {
         yield OS.File.removeDir(this.trashDir, { ignoreAbsent: true });
       }
 
       yield OS.File.removeDir(this.installPath, { ignoreAbsent: true });
 
       yield OS.File.removeDir(appProfileDir, { ignoreAbsent: true });
     });
   }
+
+  this.profilesIni = OS.Path.join(this.profileRoot, "profiles.ini");
+
+  let profileDir;
+
+  Object.defineProperty(this, "profileDir", {
+    get: function() {
+      if (!profileDir && this.profileRelPath) {
+        return getFile.apply(null, [this.profileRoot].concat(this.profileRelPath.split("/")));
+      }
+
+      return profileDir;
+    },
+    set: function(aVal) {
+      profileDir = aVal;
+    },
+  });
+
+  Object.defineProperty(this, "cacheDir", {
+    get: function() {
+      if (!this.profileRelPath) {
+        return null;
+      }
+
+      return getFile.apply(null, [this.cacheRoot].concat(this.profileRelPath.split("/")));
+    },
+  });
+
+  Object.defineProperty(this, "profileRelPath", {
+    get: function() {
+      // If the profileDir was set by someone else, use its leafName
+      // as the profile name.
+      if (profileDir) {
+        return profileDir.leafName;
+      }
+
+      // Otherwise, read profiles.ini to get the profile directory
+      try {
+        let iniParser = Cc["@mozilla.org/xpcom/ini-processor-factory;1"].
+                        getService(Ci.nsIINIParserFactory).
+                        createINIParser(getFile(this.profilesIni));
+        return iniParser.getString("Profile0", "Path");
+      } catch (e) {
+        return null;
+      }
+    }
+  });
 }
 
 function buildAppPackage(aManifest, aIconFile) {
   let zipFile = getFile(OS.Constants.Path.profileDir, "sample.zip");
 
   let zipWriter = Cc["@mozilla.org/zipwriter;1"].createInstance(Ci.nsIZipWriter);
   zipWriter.open(zipFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
   zipWriter.addEntryFile("index.html",
copy from toolkit/webapps/tests/test_custom_origin.xul
copy to toolkit/webapps/tests/test_install_appcache.xul
--- a/toolkit/webapps/tests/test_custom_origin.xul
+++ b/toolkit/webapps/tests/test_install_appcache.xul
@@ -1,130 +1,120 @@
 <?xml version="1.0"?>
 <?xml-stylesheet type="text/css" href="chrome://global/skin"?>
 <?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
 <!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1029674
+https://bugzilla.mozilla.org/show_bug.cgi?id=1034730
 -->
-<window title="Mozilla Bug 1029674"
+<window title="Mozilla Bug 1034730"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/chrome-harness.js"></script>
   <script type="application/javascript" src="head.js"/>
 
   <!-- test results are displayed in the html:body -->
   <body xmlns="http://www.w3.org/1999/xhtml">
-  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1029674"
-     target="_blank">Mozilla Bug 1029674</a>
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1034730"
+     target="_blank">Mozilla Bug 1034730</a>
   </body>
 
 <script type="application/javascript">
 <![CDATA[
 
-/** Test for Bug 1029674 **/
+/** Test for Bug 1034730 **/
 
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/NativeApp.jsm");
 Cu.import("resource://gre/modules/WebappOSUtils.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 
 let runTest = Task.async(function*() {
-  let manifest = yield readJSON(getTestFilePath("data/custom_origin.webapp"));
+  let manifest = yield readJSON(getTestFilePath("data/appcached_app/manifest.webapp"));
 
   let app = {
     name: manifest.name,
-    manifestURL: "http://test/chrome/toolkit/webapps/tests/data/custom_origin.webapp",
-    origin: "app://test.origin.privileged.app",
+    manifestURL: "http://127.0.0.1:8888/chrome/toolkit/webapps/tests/data/appcached_app/manifest.webapp",
+    origin: "http://127.0.0.1:8888/",
   };
 
-  let testAppInfo = new TestAppInfo(app, true);
+  let testAppInfo = new TestAppInfo(app, false);
 
   // Get to a clean state before the test
   yield testAppInfo.cleanup();
 
   SimpleTest.registerCleanupFunction(() => testAppInfo.cleanup());
 
   setDryRunPref();
 
-  // Use the test root certificate for the test
-  Cu.import("resource://gre/modules/StoreTrustAnchor.jsm");
-  let oldIndex = TrustedRootCertificate.index;
-  TrustedRootCertificate.index = Ci.nsIX509CertDB.AppXPCShellRoot;
-
-  SimpleTest.registerCleanupFunction(function() {
-    TrustedRootCertificate.index = oldIndex;
-  });
-
-  // Allow signed apps to be installed from the test origin
-  let oldSignedAppOrigins;
-  try {
-    oldSignedAppOrigins = Services.prefs.getCharPref("dom.mozApps.signed_apps_installable_from");
-  } catch (ex) {}
-
-  let newSignedAppOrigins = oldSignedAppOrigins.concat(",chrome://mochitests");
-  Services.prefs.setCharPref("dom.mozApps.signed_apps_installable_from", newSignedAppOrigins);
-
-  SimpleTest.registerCleanupFunction(function() {
-    Services.prefs.setCharPref("dom.mozApps.signed_apps_installable_from", oldSignedAppOrigins);
-  });
-
   // On Mac build servers, we don't have enough privileges to write to /Applications,
   // so we install apps in a user-owned directory.
   if (MAC) {
     yield setMacRootInstallDir(OS.Path.join(OS.Constants.Path.homeDir, "Applications"));
   }
 
   confirmNextInstall();
 
-  let request = navigator.mozApps.installPackage("http://test/chrome/toolkit/webapps/tests/data/custom_origin.webapp");
+  let request = navigator.mozApps.install(app.manifestURL);
 
   let (deferred = Promise.defer()) {
     request.onerror = function() {
       deferred.reject(this.error.name);
     };
     request.onsuccess = deferred.resolve;
     yield deferred.promise;
   }
 
   let appObject = request.result;
   ok(appObject, "app is non-null");
 
-  let (deferred = Promise.defer()) {
-    appObject.ondownloaderror = function() {
-      deferred.reject(this.error.name);
-    };
-    appObject.ondownloadapplied = deferred.resolve;
-    yield deferred.promise;
-  };
-
   while (!WebappOSUtils.isLaunchable(app)) {
     yield wait(1000);
   }
   ok(true, "App launchable");
 
-  let exeFile = getFile(testAppInfo.exePath);
+  let (size = 0) {
+    do {
+      try {
+        size = yield dirSize(OS.Path.join(testAppInfo.profileDir.path, "OfflineCache"));
+      } catch (e) {
+        yield wait(1000);
+      }
+    } while (size == 0);
+    ok(size > 100000, "There are some files in the OfflineCache directory");
+  }
 
-  ok(exeFile.isExecutable(), "webapprt executable is executable");
+  let exeFile = getFile(testAppInfo.exePath);
 
   let appClosed = false;
 
   testAppInfo.appProcess.init(exeFile)
   testAppInfo.appProcess.runAsync([], 0, () => appClosed = true);
 
   while (!(yield wasAppSJSAccessed()) && !appClosed) {
     yield wait(1000);
   }
   ok(!appClosed, "App was launched and is still running");
 
+  let (size = 0) {
+    do {
+      try {
+        size = yield dirSize(OS.Path.join(testAppInfo.cacheDir.path, "OfflineCache"));
+      } catch (e) {
+        yield wait(1000);
+      }
+    } while (size == 0);
+    ok(size > 100000, "There are some files in the OfflineCache directory");
+  }
+
   SimpleTest.finish();
 });
 
 runTest().catch((e) => {
   ok(false, "Error during test: " + e);
   SimpleTest.finish();
 });