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 var Cu = Components.utils;
3 Cu.import("resource://gre/modules/devtools/Loader.jsm");
4 Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
5 Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
7 const Services = devtools.require("Services");
8 const {_documentWalker} = devtools.require("devtools/server/actors/inspector");
10 // Always log packets when running tests.
11 Services.prefs.setBoolPref("devtools.debugger.log", true);
12 SimpleTest.registerCleanupFunction(function() {
13 Services.prefs.clearUserPref("devtools.debugger.log");
14 });
17 if (!DebuggerServer.initialized) {
18 DebuggerServer.init(() => true);
19 DebuggerServer.addBrowserActors();
20 SimpleTest.registerCleanupFunction(function() {
21 DebuggerServer.destroy();
22 });
23 }
25 var gAttachCleanups = [];
27 SimpleTest.registerCleanupFunction(function() {
28 for (let cleanup of gAttachCleanups) {
29 cleanup();
30 }
31 });
33 /**
34 * Open a tab, load the url, wait for it to signal its readiness,
35 * find the tab with the debugger server, and call the callback.
36 *
37 * Returns a function which can be called to close the opened ta
38 * and disconnect its debugger client.
39 */
40 function attachURL(url, callback) {
41 var win = window.open(url, "_blank");
42 var client = null;
44 let cleanup = () => {
45 if (client) {
46 client.close();
47 client = null;
48 }
49 if (win) {
50 win.close();
51 win = null;
52 }
53 };
54 gAttachCleanups.push(cleanup);
56 window.addEventListener("message", function loadListener(event) {
57 if (event.data === "ready") {
58 client = new DebuggerClient(DebuggerServer.connectPipe());
59 client.connect((applicationType, traits) => {
60 client.listTabs(response => {
61 for (let tab of response.tabs) {
62 if (tab.url === url) {
63 window.removeEventListener("message", loadListener, false);
64 client.attachTab(tab.actor, function(aResponse, aTabClient) {
65 try {
66 callback(null, client, tab, win.document);
67 } catch(ex) {
68 Cu.reportError(ex);
69 dump(ex);
70 }
71 });
72 break;
73 }
74 }
75 });
76 });
77 }
78 }, false);
80 return cleanup;
81 }
83 function promiseOnce(target, event) {
84 let deferred = promise.defer();
85 target.on(event, (...args) => {
86 if (args.length === 1) {
87 deferred.resolve(args[0]);
88 } else {
89 deferred.resolve(args);
90 }
91 });
92 return deferred.promise;
93 }
95 function sortOwnershipChildren(children) {
96 return children.sort((a, b) => a.name.localeCompare(b.name));
97 }
99 function serverOwnershipSubtree(walker, node) {
100 let actor = walker._refMap.get(node);
101 if (!actor) {
102 return undefined;
103 }
105 let children = [];
106 let docwalker = _documentWalker(node, window);
107 let child = docwalker.firstChild();
108 while (child) {
109 let item = serverOwnershipSubtree(walker, child);
110 if (item) {
111 children.push(item);
112 }
113 child = docwalker.nextSibling();
114 }
115 return {
116 name: actor.actorID,
117 children: sortOwnershipChildren(children)
118 }
119 }
121 function serverOwnershipTree(walker) {
122 let serverConnection = walker.conn._transport._serverConnection;
123 let serverWalker = serverConnection.getActor(walker.actorID);
125 return {
126 root: serverOwnershipSubtree(serverWalker, serverWalker.rootDoc ),
127 orphaned: [serverOwnershipSubtree(serverWalker, o.rawNode) for (o of serverWalker._orphaned)],
128 retained: [serverOwnershipSubtree(serverWalker, o.rawNode) for (o of serverWalker._retainedOrphans)]
129 };
130 }
132 function clientOwnershipSubtree(node) {
133 return {
134 name: node.actorID,
135 children: sortOwnershipChildren([clientOwnershipSubtree(child) for (child of node.treeChildren())])
136 }
137 }
139 function clientOwnershipTree(walker) {
140 return {
141 root: clientOwnershipSubtree(walker.rootNode),
142 orphaned: [clientOwnershipSubtree(o) for (o of walker._orphaned)],
143 retained: [clientOwnershipSubtree(o) for (o of walker._retainedOrphans)]
144 }
145 }
147 function ownershipTreeSize(tree) {
148 let size = 1;
149 for (let child of tree.children) {
150 size += ownershipTreeSize(child);
151 }
152 return size;
153 }
155 function assertOwnershipTrees(walker) {
156 let serverTree = serverOwnershipTree(walker);
157 let clientTree = clientOwnershipTree(walker);
158 is(JSON.stringify(clientTree, null, ' '), JSON.stringify(serverTree, null, ' '), "Server and client ownership trees should match.");
160 return ownershipTreeSize(clientTree.root);
161 }
163 // Verify that an actorID is inaccessible both from the client library and the server.
164 function checkMissing(client, actorID) {
165 let deferred = promise.defer();
166 let front = client.getActor(actorID);
167 ok(!front, "Front shouldn't be accessible from the client for actorID: " + actorID);
169 let deferred = promise.defer();
170 client.request({
171 to: actorID,
172 type: "request",
173 }, response => {
174 is(response.error, "noSuchActor", "node list actor should no longer be contactable.");
175 deferred.resolve(undefined);
176 });
177 return deferred.promise;
178 }
180 // Verify that an actorID is accessible both from the client library and the server.
181 function checkAvailable(client, actorID) {
182 let deferred = promise.defer();
183 let front = client.getActor(actorID);
184 ok(front, "Front should be accessible from the client for actorID: " + actorID);
186 let deferred = promise.defer();
187 client.request({
188 to: actorID,
189 type: "garbageAvailableTest",
190 }, response => {
191 is(response.error, "unrecognizedPacketType", "node list actor should be contactable.");
192 deferred.resolve(undefined);
193 });
194 return deferred.promise;
195 }
197 function promiseDone(promise) {
198 promise.then(null, err => {
199 ok(false, "Promise failed: " + err);
200 if (err.stack) {
201 dump(err.stack);
202 }
203 SimpleTest.finish();
204 });
205 }
207 // Mutation list testing
209 function isSrcChange(change) {
210 return (change.type === "attributes" && change.attributeName === "src");
211 }
213 function assertAndStrip(mutations, message, test) {
214 let size = mutations.length;
215 mutations = mutations.filter(test);
216 ok((mutations.size != size), message);
217 return mutations;
218 }
220 function isSrcChange(change) {
221 return change.type === "attributes" && change.attributeName === "src";
222 }
224 function isUnload(change) {
225 return change.type === "documentUnload";
226 }
228 function isFrameLoad(change) {
229 return change.type === "frameLoad";
230 }
232 function isUnretained(change) {
233 return change.type === "unretained";
234 }
236 function isChildList(change) {
237 return change.type === "childList";
238 }
240 function isNewRoot(change) {
241 return change.type === "newRoot";
242 }
244 // Make sure an iframe's src attribute changed and then
245 // strip that mutation out of the list.
246 function assertSrcChange(mutations) {
247 return assertAndStrip(mutations, "Should have had an iframe source change.", isSrcChange);
248 }
250 // Make sure there's an unload in the mutation list and strip
251 // that mutation out of the list
252 function assertUnload(mutations) {
253 return assertAndStrip(mutations, "Should have had a document unload change.", isUnload);
254 }
256 // Make sure there's a frame load in the mutation list and strip
257 // that mutation out of the list
258 function assertFrameLoad(mutations) {
259 return assertAndStrip(mutations, "Should have had a frame load change.", isFrameLoad);
260 }
262 // Make sure there's a childList change in the mutation list and strip
263 // that mutation out of the list
264 function assertChildList(mutations) {
265 return assertAndStrip(mutations, "Should have had a frame load change.", isChildList);
266 }
268 // Load mutations aren't predictable, so keep accumulating mutations until
269 // the one we're looking for shows up.
270 function waitForMutation(walker, test, mutations=[]) {
271 let deferred = promise.defer();
272 for (let change of mutations) {
273 if (test(change)) {
274 deferred.resolve(mutations);
275 }
276 }
278 walker.once("mutations", newMutations => {
279 waitForMutation(walker, test, mutations.concat(newMutations)).then(finalMutations => {
280 deferred.resolve(finalMutations);
281 })
282 });
284 return deferred.promise;
285 }
288 var _tests = [];
289 function addTest(test) {
290 _tests.push(test);
291 }
293 function runNextTest() {
294 if (_tests.length == 0) {
295 SimpleTest.finish()
296 return;
297 }
298 var fn = _tests.shift();
299 try {
300 fn();
301 } catch (ex) {
302 info("Test function " + (fn.name ? "'" + fn.name + "' " : "") +
303 "threw an exception: " + ex);
304 }
305 }