test_devtools_track_serviceworker_time.html (6977B)
1 <html> 2 <head> 3 <title>Bug 1251238 - track service worker install time</title> 4 <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> 5 <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> 6 </head> 7 <iframe id="iframe"></iframe> 8 <body> 9 10 <script type="text/javascript"> 11 12 const State = { 13 BYTECHECK: -1, 14 PARSED: Ci.nsIServiceWorkerInfo.STATE_PARSED, 15 INSTALLING: Ci.nsIServiceWorkerInfo.STATE_INSTALLING, 16 INSTALLED: Ci.nsIServiceWorkerInfo.STATE_INSTALLED, 17 ACTIVATING: Ci.nsIServiceWorkerInfo.STATE_ACTIVATING, 18 ACTIVATED: Ci.nsIServiceWorkerInfo.STATE_ACTIVATED, 19 REDUNDANT: Ci.nsIServiceWorkerInfo.STATE_REDUNDANT 20 }; 21 let swm = Cc["@mozilla.org/serviceworkers/manager;1"]. 22 getService(Ci.nsIServiceWorkerManager); 23 24 let EXAMPLE_URL = "https://example.com/chrome/dom/serviceworkers/test/"; 25 26 let swrlistener = null; 27 let registrationInfo = null; 28 29 // Use it to keep the sw after unregistration. 30 let astrayServiceWorkerInfo = null; 31 32 let expectedResults = [ 33 { 34 // Speacial state for verifying update since we will do the byte-check 35 // first. 36 state: State.BYTECHECK, installedTimeRecorded: false, 37 activatedTimeRecorded: false, redundantTimeRecorded: false 38 }, 39 { 40 state: State.PARSED, installedTimeRecorded: false, 41 activatedTimeRecorded: false, redundantTimeRecorded: false 42 }, 43 { 44 state: State.INSTALLING, installedTimeRecorded: false, 45 activatedTimeRecorded: false, redundantTimeRecorded: false 46 }, 47 { 48 state: State.INSTALLED, installedTimeRecorded: true, 49 activatedTimeRecorded: false, redundantTimeRecorded: false 50 }, 51 { 52 state: State.ACTIVATING, installedTimeRecorded: true, 53 activatedTimeRecorded: false, redundantTimeRecorded: false 54 }, 55 { 56 state: State.ACTIVATED, installedTimeRecorded: true, 57 activatedTimeRecorded: true, redundantTimeRecorded: false 58 }, 59 60 // When first being marked as unregistered (but the worker can remain 61 // actively controlling pages) 62 { 63 state: State.ACTIVATED, installedTimeRecorded: true, 64 activatedTimeRecorded: true, redundantTimeRecorded: false 65 }, 66 // When cleared (when idle) 67 { 68 state: State.REDUNDANT, installedTimeRecorded: true, 69 activatedTimeRecorded: true, redundantTimeRecorded: true 70 }, 71 ]; 72 73 function waitForRegister(aScope, aCallback) { 74 return new Promise(function (aResolve) { 75 let listener = { 76 onRegister (aRegistration) { 77 if (aRegistration.scope !== aScope) { 78 return; 79 } 80 swm.removeListener(listener); 81 registrationInfo = aRegistration; 82 aResolve(); 83 } 84 }; 85 swm.addListener(listener); 86 }); 87 } 88 89 function waitForUnregister(aScope) { 90 return new Promise(function (aResolve) { 91 let listener = { 92 onUnregister (aRegistration) { 93 if (aRegistration.scope !== aScope) { 94 return; 95 } 96 swm.removeListener(listener); 97 aResolve(); 98 } 99 }; 100 swm.addListener(listener); 101 }); 102 } 103 104 function register() { 105 info("Register a ServiceWorker in the iframe"); 106 107 let iframe = document.querySelector("iframe"); 108 iframe.src = EXAMPLE_URL + "serviceworkerinfo_iframe.html"; 109 110 let promise = new Promise(function(aResolve) { 111 iframe.onload = aResolve; 112 }); 113 114 return promise.then(function() { 115 iframe.contentWindow.postMessage("register", "*"); 116 return waitForRegister(EXAMPLE_URL); 117 }) 118 } 119 120 function verifyServiceWorkTime(aSWRInfo, resolve) { 121 let expectedResult = expectedResults.shift(); 122 ok(!!expectedResult, "We should be able to get test from expectedResults"); 123 124 info("Check the ServiceWorker time in its state is " + expectedResult.state); 125 126 // Get serviceWorkerInfo from swrInfo or get the astray one which we hold. 127 let swInfo = aSWRInfo.evaluatingWorker || 128 aSWRInfo.installingWorker || 129 aSWRInfo.waitingWorker || 130 aSWRInfo.activeWorker || 131 astrayServiceWorkerInfo; 132 133 ok(!!aSWRInfo.lastUpdateTime, 134 "We should do the byte-check and update the update timeStamp"); 135 136 if (!swInfo) { 137 is(expectedResult.state, State.BYTECHECK, 138 "We shouldn't get sw when we are notified for first time updating"); 139 return; 140 } 141 142 ok(!!swInfo); 143 144 is(expectedResult.state, swInfo.state, 145 "The service worker's state should be " + swInfo.state + ", but got " + 146 expectedResult.state); 147 148 is(expectedResult.installedTimeRecorded, !!swInfo.installedTime, 149 "InstalledTime should be recorded when their state is greater than " + 150 "INSTALLING"); 151 152 is(expectedResult.activatedTimeRecorded, !!swInfo.activatedTime, 153 "ActivatedTime should be recorded when their state is greater than " + 154 "ACTIVATING"); 155 156 is(expectedResult.redundantTimeRecorded, !!swInfo.redundantTime, 157 "RedundantTime should be recorded when their state is REDUNDANT"); 158 159 // We need to hold sw to avoid losing it since we'll unregister the swr later. 160 if (expectedResult.state === State.ACTIVATED) { 161 astrayServiceWorkerInfo = aSWRInfo.activeWorker; 162 163 // Resolve the promise for testServiceWorkerInfo after sw is activated. 164 resolve(); 165 } 166 } 167 168 function testServiceWorkerInfo() { 169 info("Listen onChange event and verify service worker's information"); 170 171 let promise_resolve; 172 let promise = new Promise(aResolve => promise_resolve = aResolve); 173 174 swrlistener = { 175 onChange: () => { 176 verifyServiceWorkTime(registrationInfo, promise_resolve); 177 } 178 }; 179 180 registrationInfo.addListener(swrlistener); 181 182 return promise; 183 } 184 185 async function testHttpCacheUpdateTime() { 186 let iframe = document.querySelector("iframe"); 187 let reg = await iframe.contentWindow.navigator.serviceWorker.getRegistration(); 188 let lastUpdateTime = registrationInfo.lastUpdateTime; 189 await reg.update(); 190 is(lastUpdateTime, registrationInfo.lastUpdateTime, 191 "The update time should not change when SW script is read from http cache."); 192 } 193 194 function unregister() { 195 info("Unregister the ServiceWorker"); 196 197 let iframe = document.querySelector("iframe"); 198 iframe.contentWindow.postMessage("unregister", "*"); 199 return waitForUnregister(EXAMPLE_URL); 200 } 201 202 function cleanAll() { 203 return new Promise((aResolve, aReject) => { 204 is(expectedResults.length, 0, "All the tests should be tested"); 205 206 registrationInfo.removeListener(swrlistener); 207 208 swm = null; 209 swrlistener = null; 210 registrationInfo = null; 211 astrayServiceWorkerInfo = null; 212 aResolve(); 213 }) 214 } 215 216 function runTest() { 217 return Promise.resolve() 218 .then(register) 219 .then(testServiceWorkerInfo) 220 .then(testHttpCacheUpdateTime) 221 .then(unregister) 222 .catch(aError => ok(false, "Some test failed with error " + aError)) 223 .then(cleanAll) 224 .then(SimpleTest.finish); 225 } 226 227 SimpleTest.waitForExplicitFinish(); 228 SpecialPowers.pushPrefEnv({"set": [ 229 ["dom.serviceWorkers.exemptFromPerDomainMax", true], 230 ["dom.serviceWorkers.enabled", true], 231 ["dom.serviceWorkers.testing.enabled", true] 232 ]}, runTest); 233 234 </script> 235 </body> 236 </html>