Bug 1059194 - Trusted Hosted Apps, part 3: Basic app install tests r=myk
authorFabrice Desré <fabrice@mozilla.com>
Tue, 16 Sep 2014 13:14:02 -0700
changeset 205574 18ee130341c042e5ee2ee6a75f5958b51ab34433
parent 205573 07b8b2f1345daa5498db3d0860d950c855b9f4cc
child 205575 63cfc0ff5f4a3b84e146afd4a05ee915549ebade
push id27497
push userkwierso@gmail.com
push dateTue, 16 Sep 2014 23:22:24 +0000
treeherdermozilla-central@49ef7b18963d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmyk
bugs1059194
milestone35.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 1059194 - Trusted Hosted Apps, part 3: Basic app install tests r=myk
dom/apps/tests/file_app.sjs
dom/apps/tests/file_app.template.html
dom/apps/tests/file_cached_app.template.appcache
dom/apps/tests/file_script.template.js
dom/apps/tests/file_trusted_app.template.webapp
dom/apps/tests/mochitest.ini
dom/apps/tests/test_app_update.html
--- a/dom/apps/tests/file_app.sjs
+++ b/dom/apps/tests/file_app.sjs
@@ -1,25 +1,27 @@
 var gBasePath = "tests/dom/apps/tests/";
 var gAppTemplatePath = "tests/dom/apps/tests/file_app.template.html";
+var gScriptTemplatePath = "tests/dom/apps/tests/file_script.template.js";
 var gAppcacheTemplatePath = "tests/dom/apps/tests/file_cached_app.template.appcache";
 var gWidgetTemplatePath = "tests/dom/apps/tests/file_widget_app.template.html";
 var gDefaultIcon = "default_icon";
 
 function makeResource(templatePath, version, apptype, role) {
   let icon = getState('icon') || gDefaultIcon;
   var res = readTemplate(templatePath).replace(/VERSIONTOKEN/g, version)
                                       .replace(/APPTYPETOKEN/g, apptype)
                                       .replace(/ICONTOKEN/g, icon)
                                       .replace(/ROLE/g, role);
 
   // Hack - This is necessary to make the tests pass, but hbambas says it
   // shouldn't be necessary. Comment it out and watch the tests fail.
-  if (templatePath == gAppTemplatePath && apptype == 'cached') {
-    res = res.replace('<html>', '<html manifest="file_app.sjs?apptype=cached&getappcache=true">');
+  if (templatePath == gAppTemplatePath &&
+      (apptype == 'cached' || apptype == 'trusted')) {
+    res = res.replace('<html>', '<html manifest="file_app.sjs?apptype=' + apptype + '&getappcache=true">');
   }
   return res;
 }
 
 function handleRequest(request, response) {
   var query = getQuery(request);
 
   // If this is a version update, update state and return.
@@ -42,51 +44,59 @@ function handleRequest(request, response
     response.setHeader("Content-Type", "text/html", false);
     response.setHeader("Access-Control-Allow-Origin", "*", false);
     response.write('OK');
     return;
   }
 
   // Get the app type.
   var apptype = query.apptype;
-  if (apptype != 'hosted' && apptype != 'cached' && apptype != 'widget'  && apptype != 'invalidWidget')
+  if (apptype != 'hosted' && apptype != 'cached' && apptype != 'widget'  && apptype != 'invalidWidget' && apptype != 'trusted')
     throw "Invalid app type: " + apptype;
 
   var role = query.role;
 
   // Get the version from server state and handle the etag.
   var version = Number(getState('version'));
   var etag = getEtag(request, version);
   dump("Server Etag: " + etag + "\n");
 
   if (etagMatches(request, etag)) {
-    dump("Etags Match. Sending 304\n");
+    dump("Etags Match. Sending 304 for " + request.queryString + "\n");
     response.setStatusLine(request.httpVersion, "304", "Not Modified");
     return;
   }
 
   response.setHeader("Etag", etag, false);
   if (request.hasHeader("If-None-Match"))
     dump("Client Etag: " + request.getHeader("If-None-Match") + "\n");
   else
     dump("No Client Etag\n");
 
+  // Check if we ask for the js script used in file_app.template.html
+  if ("script" in query) {
+   dump("Sending script for " + request.queryString + "\n");
+   response.write(makeResource(gScriptTemplatePath, version, apptype, role));
+   return;
+  }
+
   // Check if we're generating a webapp manifest.
   if ('getmanifest' in query) {
     var template = gBasePath + 'file_' + apptype + '_app.template.webapp';
     response.setHeader("Content-Type", "application/x-web-app-manifest+json", false);
     response.write(makeResource(template, version, apptype, role));
     return;
   }
 
   // If apptype==cached, we might be generating the appcache manifest.
   //
   // NB: Among other reasons, we use the same sjs file here so that the version
   //     state is shared.
-  if (apptype == 'cached' && 'getappcache' in query) {
+  if ((apptype == 'cached' || apptype == 'trusted') &&
+      'getappcache' in query) {
     response.setHeader("Content-Type", "text/cache-manifest", false);
     response.write(makeResource(gAppcacheTemplatePath, version, apptype, role));
     return;
   }
   else if (apptype == 'widget' || apptype == 'invalidWidget')
   {
     response.setHeader("Content-Type", "text/html", false);
     response.write(makeResource(gWidgetTemplatePath, version, apptype, role));
--- a/dom/apps/tests/file_app.template.html
+++ b/dom/apps/tests/file_app.template.html
@@ -1,67 +1,7 @@
 <html>
 <head>
-<script>
-
-function sendMessage(msg) {
-  alert(msg);
-}
-
-function ok(p, msg) {
-  if (p)
-    sendMessage("OK: " + msg);
-  else
-    sendMessage("KO: " + msg);
-}
-
-function is(a, b, msg) {
-  if (a == b)
-    sendMessage("OK: " + a + " == " + b + " - " + msg);
-  else
-    sendMessage("KO: " + a + " != " + b + " - " + msg);
-}
-
-function installed(p) {
-  if (p)
-    sendMessage("IS_INSTALLED");
-  else
-    sendMessage("NOT_INSTALLED");
-}
-
-function finish() {
-  sendMessage("VERSION: MyWebApp vVERSIONTOKEN");
-  sendMessage("DONE");
-}
-
-function cbError() {
-  ok(false, "Error callback invoked");
-  finish();
-}
-
-function go() {
-  ok(true, "Launched app");
-  var request = window.navigator.mozApps.getSelf();
-  request.onsuccess = function() {
-    var app = request.result;
-    checkApp(app);
-  }
-  request.onerror = cbError;
-}
-
-function checkApp(app) {
-  // If the app is installed, |app| will be non-null. If it is, verify its state.
-  installed(!!app);
-  if (app) {
-    var appName = "Really Rapid Release (APPTYPETOKEN)";
-    var manifest = SpecialPowers.wrap(app.manifest);
-    is(manifest.name, appName, "Manifest name should be correct");
-    is(app.origin, "http://test", "App origin should be correct");
-    is(app.installOrigin, "http://mochi.test:8888", "Install origin should be correct");
-  }
-  finish();
-}
-
-</script>
+<script src="file_app.sjs?script=true&version=VERSIONTOKEN&apptype=APPTYPETOKEN"></script>
 </head>
-<body onload="go();">
-App Body. Version: VERSIONTOKEN
+<body>
+App Body. Version: VERSIONTOKEN, Type: APPTYPETOKEN
 </body></html>
--- a/dom/apps/tests/file_cached_app.template.appcache
+++ b/dom/apps/tests/file_cached_app.template.appcache
@@ -1,3 +1,4 @@
 CACHE MANIFEST
 # Version VERSIONTOKEN
-/tests/dom/apps/tests/file_app.sjs?apptype=cached
+/tests/dom/apps/tests/file_app.sjs?apptype=APPTYPETOKEN
+/tests/dom/apps/tests/file_app.sjs?script=true&version=VERSIONTOKEN&apptype=APPTYPETOKEN
new file mode 100644
--- /dev/null
+++ b/dom/apps/tests/file_script.template.js
@@ -0,0 +1,59 @@
+function sendMessage(msg) {
+  alert(msg);
+}
+
+function ok(p, msg) {
+  if (p)
+    sendMessage("OK: " + msg);
+  else
+    sendMessage("KO: " + msg);
+}
+
+function is(a, b, msg) {
+  if (a == b)
+    sendMessage("OK: " + a + " == " + b + " - " + msg);
+  else
+    sendMessage("KO: " + a + " != " + b + " - " + msg);
+}
+
+function installed(p) {
+  if (p)
+    sendMessage("IS_INSTALLED");
+  else
+    sendMessage("NOT_INSTALLED");
+}
+
+function finish() {
+  sendMessage("VERSION: MyWebApp vVERSIONTOKEN");
+  sendMessage("DONE");
+}
+
+function cbError() {
+  ok(false, "Error callback invoked");
+  finish();
+}
+
+function go() {
+  ok(true, "Launched APPTYPETOKEN app");
+  var request = window.navigator.mozApps.getSelf();
+  request.onsuccess = function() {
+    var app = request.result;
+    checkApp(app);
+  }
+  request.onerror = cbError;
+}
+
+function checkApp(app) {
+  // If the app is installed, |app| will be non-null. If it is, verify its state.
+  installed(!!app);
+  if (app) {
+    var appName = "Really Rapid Release (APPTYPETOKEN)";
+    var manifest = SpecialPowers.wrap(app.manifest);
+    is(manifest.name, appName, "Manifest name should be correct");
+    is(app.origin, "http://test", "App origin should be correct");
+    is(app.installOrigin, "http://mochi.test:8888", "Install origin should be correct");
+  }
+  finish();
+}
+
+go();
new file mode 100644
--- /dev/null
+++ b/dom/apps/tests/file_trusted_app.template.webapp
@@ -0,0 +1,10 @@
+{
+  "type": "trusted",
+  "name": "Really Rapid Release (trusted)",
+  "description": "Updated even faster than <a href='http://mozilla.org'>Firefox</a>, just to annoy slashdotters.",
+  "launch_path": "/tests/dom/apps/tests/file_app.sjs?apptype=trusted",
+  "icons": {
+    "128": "ICONTOKEN"
+  },
+  "role": "ROLE"
+}
--- a/dom/apps/tests/mochitest.ini
+++ b/dom/apps/tests/mochitest.ini
@@ -1,17 +1,19 @@
 [DEFAULT]
 skip-if = e10s
 support-files =
   chromeAddCert.js
   file_app.sjs
   file_app.template.html
+  file_script.template.js
   file_cached_app.template.appcache
   file_cached_app.template.webapp
   file_hosted_app.template.webapp
+  file_trusted_app.template.webapp
   file_invalidWidget_app.template.webapp
   file_packaged_app.sjs
   file_packaged_app.template.html
   file_packaged_app.template.webapp
   file_widget_app.template.webapp
   file_widget_app.template.html
   signed_app.sjs
   signed_app_template.webapp
--- a/dom/apps/tests/test_app_update.html
+++ b/dom/apps/tests/test_app_update.html
@@ -12,24 +12,34 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   /** Test for Bug 826058 **/
 
   SimpleTest.waitForExplicitFinish();
 
   var gBaseURL = 'http://test/tests/dom/apps/tests/';
   var gHostedManifestURL = gBaseURL + 'file_app.sjs?apptype=hosted&getmanifest=true';
   var gCachedManifestURL = gBaseURL + 'file_app.sjs?apptype=cached&getmanifest=true';
+  var gTrustedManifestURL = gBaseURL + 'file_app.sjs?apptype=trusted&getmanifest=true';
   var gGenerator = runTest();
 
+  // We need to set the trusted hosted app csp pref since it's only in
+  // b2g.js for now.
+  function setCSPPrefs() {
+    SpecialPowers.pushPrefEnv({'set':
+      [["security.apps.trusted.CSP.default",
+        "default-src *; object-src 'none'"]]},
+      function() {  gGenerator.next(); });
+  }
+
   function go() {
     SpecialPowers.pushPermissions(
       [{ "type": "browser", "allow": 1, "context": document },
        { "type": "embed-apps", "allow": 1, "context": document },
        { "type": "webapps-manage", "allow": 1, "context": document }],
-      function() { gGenerator.next() });
+      setCSPPrefs);
   }
 
   function continueTest() {
     try {
       gGenerator.next();
     } catch (e if e instanceof StopIteration) {
       finish();
     }
@@ -154,17 +164,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     ok(app, "App is non-null");
     if (app.installState == "pending") {
       ok(true, "App is pending. Waiting for progress");
       app.onprogress = function() ok(true, "Got download progress");
       app.ondownloadsuccess = continueTest;
       app.ondownloaderror = mozAppsError;
       yield undefined;
     }
-    is(app.installState, "installed", "App is installed");
+    is(app.installState, "installed", "Cached app is installed");
 
     // Check the cached app.
     checkAppState(app, true, 3, continueTest);
     yield undefined;
 
     // Check for updates. The current infrastructure always returns a new appcache
     // manifest, so there should always be an update.
     var lastCheck = app.lastUpdateCheck;
@@ -174,22 +184,67 @@ https://bugzilla.mozilla.org/show_bug.cg
     ok(true, "Checking for updates");
     var request = app.checkForUpdate();
     request.onerror = mozAppsError;
     request.onsuccess = continueTest;
     yield undefined;
     todo(app.lastUpdateCheck > lastCheck, "lastUpdateCheck updated appropriately");
 
 
+    // Uninstall the hosted app.
+    request = navigator.mozApps.mgmt.uninstall(app);
+    request.onerror = mozAppsError;
+    request.onsuccess = continueTest;
+    yield undefined;
+    info("Uninstalled hosted appcache app");
+
+    // Install the trusted app.
+    setAppVersion(4, continueTest);
+    yield undefined;
+    ok(true, "Installing trusted app");
+    var request = navigator.mozApps.install(gTrustedManifestURL);
+    request.onerror = mozAppsError;
+    request.onsuccess = continueTest;
+    yield undefined;
+    var app = request.result;
+    ok(app, "App is non-null");
+    if (app.installState == "pending") {
+      ok(true, "App is pending. Waiting for progress");
+      app.onprogress = function() ok(true, "Got download progress");
+      app.ondownloadsuccess = continueTest;
+      app.ondownloaderror = mozAppsError;
+      yield undefined;
+    }
+    is(app.installState, "installed", "Trusted App is installed");
+    is(app.manifest.type, "trusted", "App is trusted");
+
+    // Check the cached app.
+    checkAppState(app, true, 4, continueTest);
+    yield undefined;
+
+    // Check for updates. The current infrastructure always returns a new appcache
+    // manifest, so there should always be an update.
+    var lastCheck = app.lastUpdateCheck;
+    ok(true, "Setting callbacks");
+    app.ondownloadapplied = function() ok(true, "downloadapplied fired.");
+    app.ondownloadavailable = function() ok(false, "downloadavailable fired");
+    ok(true, "Checking for updates");
+    var request = app.checkForUpdate();
+    request.onerror = mozAppsError;
+    request.onsuccess = continueTest;
+    yield undefined;
+    todo(app.lastUpdateCheck > lastCheck, "lastUpdateCheck updated appropriately");
+
+
     // Uninstall the app.
     request = navigator.mozApps.mgmt.uninstall(app);
     request.onerror = mozAppsError;
     request.onsuccess = continueTest;
     yield undefined;
-    info("Uninstalled app");
+    info("Uninstalled trusted app");
   }
 
   function setAppVersion(version, cb) {
     var xhr = new XMLHttpRequest();
     var url = gBaseURL + 'file_app.sjs?setVersion=' + version;
     xhr.addEventListener("load", function() { is(xhr.responseText, "OK", "setAppVersion OK"); cb(); });
     xhr.addEventListener("error", event => xhrError(event, url));
     xhr.addEventListener("abort", event => xhrAbort(url));