Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 const Cu = Components.utils;
2 Cu.import("resource://gre/modules/Services.jsm");
3 let tempScope = {};
4 Cu.import("resource://gre/modules/devtools/dbg-client.jsm", tempScope);
5 Cu.import("resource://gre/modules/devtools/dbg-server.jsm", tempScope);
6 Cu.import("resource://gre/modules/Promise.jsm", tempScope);
7 let {DebuggerServer, DebuggerClient, Promise} = tempScope;
8 tempScope = null;
10 const {StorageFront} = require("devtools/server/actors/storage");
11 let gTests;
12 let gExpected;
13 let index = 0;
15 const beforeReload = {
16 cookies: ["test1.example.org", "sectest1.example.org"],
17 localStorage: ["http://test1.example.org", "http://sectest1.example.org"],
18 sessionStorage: ["http://test1.example.org", "http://sectest1.example.org"],
19 };
21 function finishTests(client) {
22 // Forcing GC/CC to get rid of docshells and windows created by this test.
23 forceCollections();
24 client.close(() => {
25 forceCollections();
26 DebuggerServer.destroy();
27 forceCollections();
28 DebuggerClient = DebuggerServer = gTests = null;
29 finish();
30 });
31 }
33 function markOutMatched(toBeEmptied, data, deleted) {
34 if (!Object.keys(toBeEmptied).length) {
35 info("Object empty")
36 return;
37 }
38 ok(Object.keys(data).length,
39 "Atleast some storage types should be present in deleted");
40 for (let storageType in toBeEmptied) {
41 if (!data[storageType]) {
42 continue;
43 }
44 info("Testing for " + storageType);
45 for (let host in data[storageType]) {
46 ok(toBeEmptied[storageType][host], "Host " + host + " found");
48 for (let item of data[storageType][host]) {
49 let index = toBeEmptied[storageType][host].indexOf(item);
50 ok(index > -1, "Item found - " + item);
51 if (index > -1) {
52 toBeEmptied[storageType][host].splice(index, 1);
53 }
54 }
55 if (!toBeEmptied[storageType][host].length) {
56 delete toBeEmptied[storageType][host];
57 }
58 }
59 if (!Object.keys(toBeEmptied[storageType]).length) {
60 delete toBeEmptied[storageType];
61 }
62 }
63 }
65 function onStoresCleared(data) {
66 if (data.sessionStorage || data.localStorage) {
67 let hosts = data.sessionStorage || data.localStorage;
68 info("Stores cleared required for session storage");
69 is(hosts.length, 1, "number of hosts is 1");
70 is(hosts[0], "http://test1.example.org",
71 "host matches for " + Object.keys(data)[0]);
72 gTests.next();
73 }
74 else {
75 ok(false, "Stores cleared should only be for local and sesion storage");
76 }
78 }
80 function onStoresUpdate({added, changed, deleted}) {
81 info("inside stores update for index " + index);
83 // Here, added, changed and deleted might be null even if they are required as
84 // per gExpected. This is fine as they might come in the next stores-update
85 // call or have already come in the previous one.
86 if (added) {
87 info("matching added object for index " + index);
88 markOutMatched(gExpected.added, added);
89 }
90 if (changed) {
91 info("matching changed object for index " + index);
92 markOutMatched(gExpected.changed, changed);
93 }
94 if (deleted) {
95 info("matching deleted object for index " + index);
96 markOutMatched(gExpected.deleted, deleted);
97 }
99 if ((!gExpected.added || !Object.keys(gExpected.added).length) &&
100 (!gExpected.changed || !Object.keys(gExpected.changed).length) &&
101 (!gExpected.deleted || !Object.keys(gExpected.deleted).length)) {
102 info("Everything expected has been received for index " + index);
103 index++;
104 gTests.next();
105 }
106 else {
107 info("Still some updates pending for index " + index);
108 }
109 }
111 function* UpdateTests(front, win, client) {
112 front.on("stores-update", onStoresUpdate);
114 // index 0
115 gExpected = {
116 added: {
117 cookies: {
118 "test1.example.org": ["c1", "c2"]
119 },
120 localStorage: {
121 "http://test1.example.org": ["l1"]
122 }
123 }
124 };
125 win.addCookie("c1", "foobar1");
126 win.addCookie("c2", "foobar2");
127 win.localStorage.setItem("l1", "foobar1");
128 yield undefined;
130 // index 1
131 gExpected = {
132 changed: {
133 cookies: {
134 "test1.example.org": ["c1"]
135 }
136 },
137 added: {
138 localStorage: {
139 "http://test1.example.org": ["l2"]
140 }
141 }
142 };
143 win.addCookie("c1", "new_foobar1");
144 win.localStorage.setItem("l2", "foobar2");
145 yield undefined;
147 // index 2
148 gExpected = {
149 deleted: {
150 cookies: {
151 "test1.example.org": ["c2"]
152 },
153 localStorage: {
154 "http://test1.example.org": ["l1"]
155 }
156 },
157 added: {
158 localStorage: {
159 "http://test1.example.org": ["l3"]
160 }
161 }
162 };
163 win.removeCookie("c2");
164 win.localStorage.removeItem("l1");
165 win.localStorage.setItem("l3", "foobar3");
166 yield undefined;
168 // index 3
169 gExpected = {
170 added: {
171 cookies: {
172 "test1.example.org": ["c3"]
173 },
174 sessionStorage: {
175 "http://test1.example.org": ["s1", "s2"]
176 }
177 },
178 changed: {
179 localStorage: {
180 "http://test1.example.org": ["l3"]
181 }
182 },
183 deleted: {
184 cookies: {
185 "test1.example.org": ["c1"]
186 },
187 localStorage: {
188 "http://test1.example.org": ["l2"]
189 }
190 }
191 };
192 win.removeCookie("c1");
193 win.addCookie("c3", "foobar3");
194 win.localStorage.removeItem("l2");
195 win.sessionStorage.setItem("s1", "foobar1");
196 win.sessionStorage.setItem("s2", "foobar2");
197 win.localStorage.setItem("l3", "new_foobar3");
198 yield undefined;
200 // index 4
201 gExpected = {
202 deleted: {
203 sessionStorage: {
204 "http://test1.example.org": ["s1"]
205 }
206 }
207 };
208 win.sessionStorage.removeItem("s1");
209 yield undefined;
211 // index 5
212 gExpected = {
213 deleted: {
214 cookies: {
215 "test1.example.org": ["c3"]
216 }
217 }
218 };
219 front.on("stores-cleared", onStoresCleared);
220 win.clear();
221 yield undefined;
222 // Another 2 more yield undefined s so as to wait for the "stores-cleared" to
223 // fire. One for Local Storage and other for Session Storage
224 yield undefined;
225 yield undefined;
227 front.off("stores-cleared", onStoresCleared);
228 front.off("stores-update", onStoresUpdate);
229 finishTests(client);
230 }
233 function test() {
234 waitForExplicitFinish();
235 addTab(MAIN_DOMAIN + "storage-updates.html", function(doc) {
236 try {
237 // Sometimes debugger server does not get destroyed correctly by previous
238 // tests.
239 DebuggerServer.destroy();
240 } catch (ex) { }
241 DebuggerServer.init(function () { return true; });
242 DebuggerServer.addBrowserActors();
244 let client = new DebuggerClient(DebuggerServer.connectPipe());
245 client.connect(function onConnect() {
246 client.listTabs(function onListTabs(aResponse) {
247 let form = aResponse.tabs[aResponse.selected];
248 let front = StorageFront(client, form);
249 gTests = UpdateTests(front, doc.defaultView.wrappedJSObject,
250 client);
251 // Make an initial call to initialize the actor
252 front.listStores().then(() => gTests.next());
253 });
254 });
255 })
256 }