1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/devtools/server/tests/browser/browser_storage_updates.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,256 @@ 1.4 +const Cu = Components.utils; 1.5 +Cu.import("resource://gre/modules/Services.jsm"); 1.6 +let tempScope = {}; 1.7 +Cu.import("resource://gre/modules/devtools/dbg-client.jsm", tempScope); 1.8 +Cu.import("resource://gre/modules/devtools/dbg-server.jsm", tempScope); 1.9 +Cu.import("resource://gre/modules/Promise.jsm", tempScope); 1.10 +let {DebuggerServer, DebuggerClient, Promise} = tempScope; 1.11 +tempScope = null; 1.12 + 1.13 +const {StorageFront} = require("devtools/server/actors/storage"); 1.14 +let gTests; 1.15 +let gExpected; 1.16 +let index = 0; 1.17 + 1.18 +const beforeReload = { 1.19 + cookies: ["test1.example.org", "sectest1.example.org"], 1.20 + localStorage: ["http://test1.example.org", "http://sectest1.example.org"], 1.21 + sessionStorage: ["http://test1.example.org", "http://sectest1.example.org"], 1.22 +}; 1.23 + 1.24 +function finishTests(client) { 1.25 + // Forcing GC/CC to get rid of docshells and windows created by this test. 1.26 + forceCollections(); 1.27 + client.close(() => { 1.28 + forceCollections(); 1.29 + DebuggerServer.destroy(); 1.30 + forceCollections(); 1.31 + DebuggerClient = DebuggerServer = gTests = null; 1.32 + finish(); 1.33 + }); 1.34 +} 1.35 + 1.36 +function markOutMatched(toBeEmptied, data, deleted) { 1.37 + if (!Object.keys(toBeEmptied).length) { 1.38 + info("Object empty") 1.39 + return; 1.40 + } 1.41 + ok(Object.keys(data).length, 1.42 + "Atleast some storage types should be present in deleted"); 1.43 + for (let storageType in toBeEmptied) { 1.44 + if (!data[storageType]) { 1.45 + continue; 1.46 + } 1.47 + info("Testing for " + storageType); 1.48 + for (let host in data[storageType]) { 1.49 + ok(toBeEmptied[storageType][host], "Host " + host + " found"); 1.50 + 1.51 + for (let item of data[storageType][host]) { 1.52 + let index = toBeEmptied[storageType][host].indexOf(item); 1.53 + ok(index > -1, "Item found - " + item); 1.54 + if (index > -1) { 1.55 + toBeEmptied[storageType][host].splice(index, 1); 1.56 + } 1.57 + } 1.58 + if (!toBeEmptied[storageType][host].length) { 1.59 + delete toBeEmptied[storageType][host]; 1.60 + } 1.61 + } 1.62 + if (!Object.keys(toBeEmptied[storageType]).length) { 1.63 + delete toBeEmptied[storageType]; 1.64 + } 1.65 + } 1.66 +} 1.67 + 1.68 +function onStoresCleared(data) { 1.69 + if (data.sessionStorage || data.localStorage) { 1.70 + let hosts = data.sessionStorage || data.localStorage; 1.71 + info("Stores cleared required for session storage"); 1.72 + is(hosts.length, 1, "number of hosts is 1"); 1.73 + is(hosts[0], "http://test1.example.org", 1.74 + "host matches for " + Object.keys(data)[0]); 1.75 + gTests.next(); 1.76 + } 1.77 + else { 1.78 + ok(false, "Stores cleared should only be for local and sesion storage"); 1.79 + } 1.80 + 1.81 +} 1.82 + 1.83 +function onStoresUpdate({added, changed, deleted}) { 1.84 + info("inside stores update for index " + index); 1.85 + 1.86 + // Here, added, changed and deleted might be null even if they are required as 1.87 + // per gExpected. This is fine as they might come in the next stores-update 1.88 + // call or have already come in the previous one. 1.89 + if (added) { 1.90 + info("matching added object for index " + index); 1.91 + markOutMatched(gExpected.added, added); 1.92 + } 1.93 + if (changed) { 1.94 + info("matching changed object for index " + index); 1.95 + markOutMatched(gExpected.changed, changed); 1.96 + } 1.97 + if (deleted) { 1.98 + info("matching deleted object for index " + index); 1.99 + markOutMatched(gExpected.deleted, deleted); 1.100 + } 1.101 + 1.102 + if ((!gExpected.added || !Object.keys(gExpected.added).length) && 1.103 + (!gExpected.changed || !Object.keys(gExpected.changed).length) && 1.104 + (!gExpected.deleted || !Object.keys(gExpected.deleted).length)) { 1.105 + info("Everything expected has been received for index " + index); 1.106 + index++; 1.107 + gTests.next(); 1.108 + } 1.109 + else { 1.110 + info("Still some updates pending for index " + index); 1.111 + } 1.112 +} 1.113 + 1.114 +function* UpdateTests(front, win, client) { 1.115 + front.on("stores-update", onStoresUpdate); 1.116 + 1.117 + // index 0 1.118 + gExpected = { 1.119 + added: { 1.120 + cookies: { 1.121 + "test1.example.org": ["c1", "c2"] 1.122 + }, 1.123 + localStorage: { 1.124 + "http://test1.example.org": ["l1"] 1.125 + } 1.126 + } 1.127 + }; 1.128 + win.addCookie("c1", "foobar1"); 1.129 + win.addCookie("c2", "foobar2"); 1.130 + win.localStorage.setItem("l1", "foobar1"); 1.131 + yield undefined; 1.132 + 1.133 + // index 1 1.134 + gExpected = { 1.135 + changed: { 1.136 + cookies: { 1.137 + "test1.example.org": ["c1"] 1.138 + } 1.139 + }, 1.140 + added: { 1.141 + localStorage: { 1.142 + "http://test1.example.org": ["l2"] 1.143 + } 1.144 + } 1.145 + }; 1.146 + win.addCookie("c1", "new_foobar1"); 1.147 + win.localStorage.setItem("l2", "foobar2"); 1.148 + yield undefined; 1.149 + 1.150 + // index 2 1.151 + gExpected = { 1.152 + deleted: { 1.153 + cookies: { 1.154 + "test1.example.org": ["c2"] 1.155 + }, 1.156 + localStorage: { 1.157 + "http://test1.example.org": ["l1"] 1.158 + } 1.159 + }, 1.160 + added: { 1.161 + localStorage: { 1.162 + "http://test1.example.org": ["l3"] 1.163 + } 1.164 + } 1.165 + }; 1.166 + win.removeCookie("c2"); 1.167 + win.localStorage.removeItem("l1"); 1.168 + win.localStorage.setItem("l3", "foobar3"); 1.169 + yield undefined; 1.170 + 1.171 + // index 3 1.172 + gExpected = { 1.173 + added: { 1.174 + cookies: { 1.175 + "test1.example.org": ["c3"] 1.176 + }, 1.177 + sessionStorage: { 1.178 + "http://test1.example.org": ["s1", "s2"] 1.179 + } 1.180 + }, 1.181 + changed: { 1.182 + localStorage: { 1.183 + "http://test1.example.org": ["l3"] 1.184 + } 1.185 + }, 1.186 + deleted: { 1.187 + cookies: { 1.188 + "test1.example.org": ["c1"] 1.189 + }, 1.190 + localStorage: { 1.191 + "http://test1.example.org": ["l2"] 1.192 + } 1.193 + } 1.194 + }; 1.195 + win.removeCookie("c1"); 1.196 + win.addCookie("c3", "foobar3"); 1.197 + win.localStorage.removeItem("l2"); 1.198 + win.sessionStorage.setItem("s1", "foobar1"); 1.199 + win.sessionStorage.setItem("s2", "foobar2"); 1.200 + win.localStorage.setItem("l3", "new_foobar3"); 1.201 + yield undefined; 1.202 + 1.203 + // index 4 1.204 + gExpected = { 1.205 + deleted: { 1.206 + sessionStorage: { 1.207 + "http://test1.example.org": ["s1"] 1.208 + } 1.209 + } 1.210 + }; 1.211 + win.sessionStorage.removeItem("s1"); 1.212 + yield undefined; 1.213 + 1.214 + // index 5 1.215 + gExpected = { 1.216 + deleted: { 1.217 + cookies: { 1.218 + "test1.example.org": ["c3"] 1.219 + } 1.220 + } 1.221 + }; 1.222 + front.on("stores-cleared", onStoresCleared); 1.223 + win.clear(); 1.224 + yield undefined; 1.225 + // Another 2 more yield undefined s so as to wait for the "stores-cleared" to 1.226 + // fire. One for Local Storage and other for Session Storage 1.227 + yield undefined; 1.228 + yield undefined; 1.229 + 1.230 + front.off("stores-cleared", onStoresCleared); 1.231 + front.off("stores-update", onStoresUpdate); 1.232 + finishTests(client); 1.233 +} 1.234 + 1.235 + 1.236 +function test() { 1.237 + waitForExplicitFinish(); 1.238 + addTab(MAIN_DOMAIN + "storage-updates.html", function(doc) { 1.239 + try { 1.240 + // Sometimes debugger server does not get destroyed correctly by previous 1.241 + // tests. 1.242 + DebuggerServer.destroy(); 1.243 + } catch (ex) { } 1.244 + DebuggerServer.init(function () { return true; }); 1.245 + DebuggerServer.addBrowserActors(); 1.246 + 1.247 + let client = new DebuggerClient(DebuggerServer.connectPipe()); 1.248 + client.connect(function onConnect() { 1.249 + client.listTabs(function onListTabs(aResponse) { 1.250 + let form = aResponse.tabs[aResponse.selected]; 1.251 + let front = StorageFront(client, form); 1.252 + gTests = UpdateTests(front, doc.defaultView.wrappedJSObject, 1.253 + client); 1.254 + // Make an initial call to initialize the actor 1.255 + front.listStores().then(() => gTests.next()); 1.256 + }); 1.257 + }); 1.258 + }) 1.259 +}