Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | <!DOCTYPE HTML> |
michael@0 | 2 | <html> |
michael@0 | 3 | <!-- |
michael@0 | 4 | https://bugzilla.mozilla.org/show_bug.cgi?id=826058 |
michael@0 | 5 | --> |
michael@0 | 6 | <head> |
michael@0 | 7 | <meta charset="utf-8"> |
michael@0 | 8 | <title>Test for Bug 826058</title> |
michael@0 | 9 | <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
michael@0 | 10 | <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> |
michael@0 | 11 | <script type="application/javascript;version=1.7"> |
michael@0 | 12 | |
michael@0 | 13 | /** Test for Bug 826058 **/ |
michael@0 | 14 | |
michael@0 | 15 | SimpleTest.waitForExplicitFinish(); |
michael@0 | 16 | |
michael@0 | 17 | var gBaseURL = 'http://test/tests/dom/apps/tests/'; |
michael@0 | 18 | var gHostedManifestURL = gBaseURL + 'file_app.sjs?apptype=hosted&getmanifest=true'; |
michael@0 | 19 | var gCachedManifestURL = gBaseURL + 'file_app.sjs?apptype=cached&getmanifest=true'; |
michael@0 | 20 | var gGenerator = runTest(); |
michael@0 | 21 | |
michael@0 | 22 | function go() { |
michael@0 | 23 | SpecialPowers.pushPermissions( |
michael@0 | 24 | [{ "type": "browser", "allow": 1, "context": document }, |
michael@0 | 25 | { "type": "embed-apps", "allow": 1, "context": document }, |
michael@0 | 26 | { "type": "webapps-manage", "allow": 1, "context": document }], |
michael@0 | 27 | function() { gGenerator.next() }); |
michael@0 | 28 | } |
michael@0 | 29 | |
michael@0 | 30 | function continueTest() { |
michael@0 | 31 | try { |
michael@0 | 32 | gGenerator.next(); |
michael@0 | 33 | } catch (e if e instanceof StopIteration) { |
michael@0 | 34 | finish(); |
michael@0 | 35 | } |
michael@0 | 36 | } |
michael@0 | 37 | |
michael@0 | 38 | function mozAppsError() { |
michael@0 | 39 | ok(false, "mozApps error: " + this.error.name); |
michael@0 | 40 | finish(); |
michael@0 | 41 | } |
michael@0 | 42 | |
michael@0 | 43 | function xhrError(event, url) { |
michael@0 | 44 | var xhr = event.target; |
michael@0 | 45 | ok(false, "XHR error loading " + url + ": " + xhr.status + " - " + |
michael@0 | 46 | xhr.statusText); |
michael@0 | 47 | finish(); |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | function xhrAbort(url) { |
michael@0 | 51 | ok(false, "XHR abort loading " + url); |
michael@0 | 52 | finish(); |
michael@0 | 53 | } |
michael@0 | 54 | |
michael@0 | 55 | function runTest() { |
michael@0 | 56 | // Set up. |
michael@0 | 57 | |
michael@0 | 58 | SpecialPowers.setAllAppsLaunchable(true); |
michael@0 | 59 | SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true); |
michael@0 | 60 | |
michael@0 | 61 | // Test Bug 927699 - navigator.mozApps.install(url) lets NS_ERROR_FAILURE |
michael@0 | 62 | // onto the web |
michael@0 | 63 | var request = navigator.mozApps.install(""); |
michael@0 | 64 | request.onerror = function() { |
michael@0 | 65 | ok(request.error.name == "INVALID_URL", "Got expected INVALID_URL"); |
michael@0 | 66 | continueTest(); |
michael@0 | 67 | }; |
michael@0 | 68 | request.onsuccess = mozAppsError; |
michael@0 | 69 | yield undefined; |
michael@0 | 70 | |
michael@0 | 71 | setAppVersion(1, continueTest); |
michael@0 | 72 | yield undefined; |
michael@0 | 73 | SpecialPowers.autoConfirmAppInstall(continueTest); |
michael@0 | 74 | yield undefined; |
michael@0 | 75 | |
michael@0 | 76 | // Load the app, uninstalled. |
michael@0 | 77 | checkAppState(null, false, 1, continueTest); |
michael@0 | 78 | yield undefined; |
michael@0 | 79 | |
michael@0 | 80 | // Bump the version and install the app. |
michael@0 | 81 | setAppVersion(2, continueTest); |
michael@0 | 82 | yield undefined; |
michael@0 | 83 | |
michael@0 | 84 | request = navigator.mozApps.install(gHostedManifestURL); |
michael@0 | 85 | request.onerror = mozAppsError; |
michael@0 | 86 | request.onsuccess = continueTest; |
michael@0 | 87 | yield undefined; |
michael@0 | 88 | var app = request.result; |
michael@0 | 89 | ok(app, "App is non-null"); |
michael@0 | 90 | ok(app.manifest.description == "Updated even faster than Firefox, just to annoy slashdotters.", |
michael@0 | 91 | "Manifest is HTML-sanitized"); |
michael@0 | 92 | |
michael@0 | 93 | // Check the app a few times. |
michael@0 | 94 | checkAppState(app, true, 2, continueTest); |
michael@0 | 95 | yield undefined; |
michael@0 | 96 | checkAppState(app, true, 2, continueTest); |
michael@0 | 97 | yield undefined; |
michael@0 | 98 | |
michael@0 | 99 | // Bump the version and check the app again. The app is not cached, so the |
michael@0 | 100 | // version bump takes effect. |
michael@0 | 101 | setAppVersion(3, continueTest); |
michael@0 | 102 | yield undefined; |
michael@0 | 103 | checkAppState(app, true, 3, continueTest); |
michael@0 | 104 | yield undefined; |
michael@0 | 105 | |
michael@0 | 106 | // check for update |
michael@0 | 107 | var icons = app.manifest.icons; |
michael@0 | 108 | var oldIcon = icons[Object.keys(icons)[0]]; |
michael@0 | 109 | var oldUpdateTime = app.updateTime; |
michael@0 | 110 | setAppIcon('new_icon', continueTest); |
michael@0 | 111 | yield undefined; |
michael@0 | 112 | |
michael@0 | 113 | app.ondownloadavailable = function() { |
michael@0 | 114 | ok(false, 'Got a downloadavailable event for non-cached hosted apps'); |
michael@0 | 115 | }; |
michael@0 | 116 | |
michael@0 | 117 | app.ondownloadapplied = function() { |
michael@0 | 118 | ok(true, 'Got a downloadapplied when checking for update'); |
michael@0 | 119 | app.ondownloadapplied = app.ondownloadavailable = null; |
michael@0 | 120 | continueTest(); |
michael@0 | 121 | }; |
michael@0 | 122 | request = app.checkForUpdate(); |
michael@0 | 123 | request.onerror = mozAppsError; |
michael@0 | 124 | request.onsuccess = function() { |
michael@0 | 125 | ok(true, "Got onsuccess"); |
michael@0 | 126 | continueTest(); |
michael@0 | 127 | }; |
michael@0 | 128 | yield undefined; |
michael@0 | 129 | yield undefined; |
michael@0 | 130 | |
michael@0 | 131 | icons = app.manifest.icons; |
michael@0 | 132 | var newIcon = icons[Object.keys(icons)[0]]; |
michael@0 | 133 | var newUpdateTime = app.updateTime; |
michael@0 | 134 | isnot(oldIcon, newIcon, 'The icon should be updated'); |
michael@0 | 135 | isnot(oldUpdateTime, newUpdateTime, 'The update time should be updated'); |
michael@0 | 136 | |
michael@0 | 137 | // Uninstall the app. |
michael@0 | 138 | request = navigator.mozApps.mgmt.uninstall(app); |
michael@0 | 139 | request.onerror = mozAppsError; |
michael@0 | 140 | request.onsuccess = continueTest; |
michael@0 | 141 | yield undefined; |
michael@0 | 142 | |
michael@0 | 143 | // Check the uninstalled app. |
michael@0 | 144 | checkAppState(app, false, 3, continueTest); |
michael@0 | 145 | yield undefined; |
michael@0 | 146 | |
michael@0 | 147 | // Install the cached app. |
michael@0 | 148 | setAppVersion(3, continueTest); |
michael@0 | 149 | yield undefined; |
michael@0 | 150 | ok(true, "Installing cached app"); |
michael@0 | 151 | var request = navigator.mozApps.install(gCachedManifestURL); |
michael@0 | 152 | request.onerror = mozAppsError; |
michael@0 | 153 | request.onsuccess = continueTest; |
michael@0 | 154 | yield undefined; |
michael@0 | 155 | var app = request.result; |
michael@0 | 156 | ok(app, "App is non-null"); |
michael@0 | 157 | if (app.installState == "pending") { |
michael@0 | 158 | ok(true, "App is pending. Waiting for progress"); |
michael@0 | 159 | app.onprogress = function() ok(true, "Got download progress"); |
michael@0 | 160 | app.ondownloadsuccess = continueTest; |
michael@0 | 161 | app.ondownloaderror = mozAppsError; |
michael@0 | 162 | yield undefined; |
michael@0 | 163 | } |
michael@0 | 164 | is(app.installState, "installed", "App is installed"); |
michael@0 | 165 | |
michael@0 | 166 | // Check the cached app. |
michael@0 | 167 | checkAppState(app, true, 3, continueTest); |
michael@0 | 168 | yield undefined; |
michael@0 | 169 | |
michael@0 | 170 | // Check for updates. The current infrastructure always returns a new appcache |
michael@0 | 171 | // manifest, so there should always be an update. |
michael@0 | 172 | var lastCheck = app.lastUpdateCheck; |
michael@0 | 173 | ok(true, "Setting callbacks"); |
michael@0 | 174 | app.ondownloadapplied = function() ok(true, "downloadapplied fired."); |
michael@0 | 175 | app.ondownloadavailable = function() ok(false, "downloadavailable fired"); |
michael@0 | 176 | ok(true, "Checking for updates"); |
michael@0 | 177 | var request = app.checkForUpdate(); |
michael@0 | 178 | request.onerror = mozAppsError; |
michael@0 | 179 | request.onsuccess = continueTest; |
michael@0 | 180 | yield undefined; |
michael@0 | 181 | todo(app.lastUpdateCheck > lastCheck, "lastUpdateCheck updated appropriately"); |
michael@0 | 182 | |
michael@0 | 183 | |
michael@0 | 184 | // Uninstall the app. |
michael@0 | 185 | request = navigator.mozApps.mgmt.uninstall(app); |
michael@0 | 186 | request.onerror = mozAppsError; |
michael@0 | 187 | request.onsuccess = continueTest; |
michael@0 | 188 | yield undefined; |
michael@0 | 189 | ok(true, "Uninstalled app"); |
michael@0 | 190 | |
michael@0 | 191 | // Check the uninstalled app. |
michael@0 | 192 | checkAppState(app, false, 3, continueTest); |
michael@0 | 193 | yield undefined; |
michael@0 | 194 | } |
michael@0 | 195 | |
michael@0 | 196 | function setAppVersion(version, cb) { |
michael@0 | 197 | var xhr = new XMLHttpRequest(); |
michael@0 | 198 | var url = gBaseURL + 'file_app.sjs?setVersion=' + version; |
michael@0 | 199 | xhr.addEventListener("load", function() { is(xhr.responseText, "OK", "setAppVersion OK"); cb(); }); |
michael@0 | 200 | xhr.addEventListener("error", event => xhrError(event, url)); |
michael@0 | 201 | xhr.addEventListener("abort", event => xhrAbort(url)); |
michael@0 | 202 | xhr.open('GET', url, true); |
michael@0 | 203 | xhr.send(); |
michael@0 | 204 | } |
michael@0 | 205 | |
michael@0 | 206 | function setAppIcon(icon, cb) { |
michael@0 | 207 | var xhr = new XMLHttpRequest(); |
michael@0 | 208 | var url = gBaseURL + 'file_app.sjs?setIcon=' + icon; |
michael@0 | 209 | xhr.addEventListener("load", function() { is(xhr.responseText, "OK", "setAppIcon OK"); cb(); }); |
michael@0 | 210 | xhr.addEventListener("error", event => xhrError(event, url)); |
michael@0 | 211 | xhr.addEventListener("abort", event => xhrAbort(url)); |
michael@0 | 212 | xhr.open('GET', url, true); |
michael@0 | 213 | xhr.send(); |
michael@0 | 214 | } |
michael@0 | 215 | |
michael@0 | 216 | // This function checks the state of an installed app. It does the following: |
michael@0 | 217 | // |
michael@0 | 218 | // * Check various state on the app object itself. |
michael@0 | 219 | // * Launch the app. |
michael@0 | 220 | // * Listen for messages from the app, verifying state. |
michael@0 | 221 | // * Close the app. |
michael@0 | 222 | // * Invoke the callback. |
michael@0 | 223 | function checkAppState(app, installed, version, cb) { |
michael@0 | 224 | // Check state on the app object. |
michael@0 | 225 | if (installed) |
michael@0 | 226 | is(app.installState, "installed", "Checking installed app"); |
michael@0 | 227 | else |
michael@0 | 228 | ok(true, "Checking uninstalled app"); |
michael@0 | 229 | |
michael@0 | 230 | // Set up the app. We need to set the attributes before the app is inserted |
michael@0 | 231 | // into the DOM. |
michael@0 | 232 | var ifr = document.createElement('iframe'); |
michael@0 | 233 | ifr.setAttribute('mozbrowser', 'true'); |
michael@0 | 234 | ifr.setAttribute('mozapp', app ? app.manifestURL : gHostedManifestURL); |
michael@0 | 235 | ifr.setAttribute('src', getAppURL(app)); |
michael@0 | 236 | var domParent = document.getElementById('container'); |
michael@0 | 237 | |
michael@0 | 238 | // Set us up to listen for messages from the app. |
michael@0 | 239 | var listener = function(e) { |
michael@0 | 240 | var message = e.detail.message; |
michael@0 | 241 | if (/OK/.exec(message)) { |
michael@0 | 242 | ok(true, "Message from app: " + message); |
michael@0 | 243 | } else if (/KO/.exec(message)) { |
michael@0 | 244 | ok(false, "Message from app: " + message); |
michael@0 | 245 | } else if (/IS_INSTALLED/.exec(message)) { |
michael@0 | 246 | ok(installed, "App is installed"); |
michael@0 | 247 | } else if (/NOT_INSTALLED/.exec(message)) { |
michael@0 | 248 | ok(!installed, "App is not installed"); |
michael@0 | 249 | } else if (/VERSION/.exec(message)) { |
michael@0 | 250 | is(message, "VERSION: MyWebApp v" + version, "Version should be correct"); |
michael@0 | 251 | } else if (/DONE/.exec(message)) { |
michael@0 | 252 | ok(true, "Messaging from app complete"); |
michael@0 | 253 | ifr.removeEventListener('mozbrowsershowmodalprompt', listener); |
michael@0 | 254 | domParent.removeChild(ifr); |
michael@0 | 255 | cb(); |
michael@0 | 256 | } |
michael@0 | 257 | } |
michael@0 | 258 | |
michael@0 | 259 | // This event is triggered when the app calls "alert". |
michael@0 | 260 | ifr.addEventListener('mozbrowsershowmodalprompt', listener, false); |
michael@0 | 261 | |
michael@0 | 262 | // Add the iframe to the DOM, triggering the launch. |
michael@0 | 263 | domParent.appendChild(ifr); |
michael@0 | 264 | } |
michael@0 | 265 | |
michael@0 | 266 | // Returns that appropriate path for the app associated with the manifest, |
michael@0 | 267 | // or the base sjs file if app is null. |
michael@0 | 268 | function getAppURL(app) { |
michael@0 | 269 | if (!app) |
michael@0 | 270 | return gBaseURL + "file_app.sjs?apptype=hosted"; |
michael@0 | 271 | return app.origin + app.manifest.launch_path; |
michael@0 | 272 | } |
michael@0 | 273 | |
michael@0 | 274 | function finish() { |
michael@0 | 275 | SpecialPowers.clearUserPref("dom.mozBrowserFramesEnabled"); |
michael@0 | 276 | SimpleTest.finish(); |
michael@0 | 277 | } |
michael@0 | 278 | |
michael@0 | 279 | function doReload() { |
michael@0 | 280 | window.location.reload(true); |
michael@0 | 281 | } |
michael@0 | 282 | |
michael@0 | 283 | </script> |
michael@0 | 284 | </head> |
michael@0 | 285 | <body onload="go()"> |
michael@0 | 286 | <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=826058">Mozilla Bug 826058</a> |
michael@0 | 287 | <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=863337">Mozilla Bug 863337</a> |
michael@0 | 288 | <p id="display"></p> |
michael@0 | 289 | <div id="content" style="display: none"> |
michael@0 | 290 | |
michael@0 | 291 | </div> |
michael@0 | 292 | <pre id="test"> |
michael@0 | 293 | </pre> |
michael@0 | 294 | <div id="container"></div> |
michael@0 | 295 | <button onclick="doReload()">Reload Page</button> |
michael@0 | 296 | </body> |
michael@0 | 297 | </html> |