Bug 1059194 - Trusted Hosted Apps, part 3: Basic app install tests r=myk a=bajaj
authorFabrice Desré <fabrice@mozilla.com>
Tue, 16 Sep 2014 13:14:02 -0700
changeset 224911 7ff763eb328b495b4e2517221db31f5dec5759ff
parent 224910 e7ad69c3b90c5b06d0c2f4e25c8b93db7753c927
child 224912 f61e00dd4325974d525da5728e356f8fb0d21c24
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmyk, bajaj
bugs1059194
milestone34.0a2
Bug 1059194 - Trusted Hosted Apps, part 3: Basic app install tests r=myk a=bajaj
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));