|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 "use strict"; |
|
5 |
|
6 const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
|
7 |
|
8 const XHTML_NS = "http://www.w3.org/1999/xhtml"; |
|
9 |
|
10 Cu.import("resource://gre/modules/Services.jsm"); |
|
11 |
|
12 let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools; |
|
13 let WebConsoleUtils = devtools.require("devtools/toolkit/webconsole/utils").Utils; |
|
14 |
|
15 let ConsoleAPIStorage = Cc["@mozilla.org/consoleAPI-storage;1"] |
|
16 .getService(Ci.nsIConsoleAPIStorage); |
|
17 |
|
18 let {ConsoleServiceListener, ConsoleAPIListener} = |
|
19 devtools.require("devtools/toolkit/webconsole/utils"); |
|
20 |
|
21 function initCommon() |
|
22 { |
|
23 //Services.prefs.setBoolPref("devtools.debugger.log", true); |
|
24 |
|
25 Cu.import("resource://gre/modules/devtools/dbg-server.jsm"); |
|
26 Cu.import("resource://gre/modules/devtools/dbg-client.jsm"); |
|
27 } |
|
28 |
|
29 function initDebuggerServer() |
|
30 { |
|
31 if (!DebuggerServer.initialized) { |
|
32 DebuggerServer.init(); |
|
33 DebuggerServer.addBrowserActors(); |
|
34 } |
|
35 } |
|
36 |
|
37 function connectToDebugger(aCallback) |
|
38 { |
|
39 initCommon(); |
|
40 initDebuggerServer(); |
|
41 |
|
42 let transport = DebuggerServer.connectPipe(); |
|
43 let client = new DebuggerClient(transport); |
|
44 |
|
45 let dbgState = { dbgClient: client }; |
|
46 client.connect(aCallback.bind(null, dbgState)); |
|
47 } |
|
48 |
|
49 function attachConsole(aListeners, aCallback, aAttachToTab) |
|
50 { |
|
51 function _onAttachConsole(aState, aResponse, aWebConsoleClient) |
|
52 { |
|
53 if (aResponse.error) { |
|
54 Cu.reportError("attachConsole failed: " + aResponse.error + " " + |
|
55 aResponse.message); |
|
56 } |
|
57 |
|
58 aState.client = aWebConsoleClient; |
|
59 |
|
60 aCallback(aState, aResponse); |
|
61 } |
|
62 |
|
63 connectToDebugger(function _onConnect(aState, aResponse) { |
|
64 if (aResponse.error) { |
|
65 Cu.reportError("client.connect() failed: " + aResponse.error + " " + |
|
66 aResponse.message); |
|
67 aCallback(aState, aResponse); |
|
68 return; |
|
69 } |
|
70 |
|
71 aState.dbgClient.listTabs(function _onListTabs(aResponse) { |
|
72 if (aResponse.error) { |
|
73 Cu.reportError("listTabs failed: " + aResponse.error + " " + |
|
74 aResponse.message); |
|
75 aCallback(aState, aResponse); |
|
76 return; |
|
77 } |
|
78 let consoleActor = aAttachToTab ? |
|
79 aResponse.tabs[aResponse.selected].consoleActor : |
|
80 aResponse.consoleActor; |
|
81 aState.actor = consoleActor; |
|
82 aState.dbgClient.attachConsole(consoleActor, aListeners, |
|
83 _onAttachConsole.bind(null, aState)); |
|
84 }); |
|
85 }); |
|
86 } |
|
87 |
|
88 function closeDebugger(aState, aCallback) |
|
89 { |
|
90 aState.dbgClient.close(aCallback); |
|
91 aState.dbgClient = null; |
|
92 aState.client = null; |
|
93 } |
|
94 |
|
95 function checkConsoleAPICall(aCall, aExpected) |
|
96 { |
|
97 if (aExpected.level != "trace" && aExpected.arguments) { |
|
98 is(aCall.arguments.length, aExpected.arguments.length, |
|
99 "number of arguments"); |
|
100 } |
|
101 |
|
102 checkObject(aCall, aExpected); |
|
103 } |
|
104 |
|
105 function checkObject(aObject, aExpected) |
|
106 { |
|
107 for (let name of Object.keys(aExpected)) |
|
108 { |
|
109 let expected = aExpected[name]; |
|
110 let value = aObject[name]; |
|
111 checkValue(name, value, expected); |
|
112 } |
|
113 } |
|
114 |
|
115 function checkValue(aName, aValue, aExpected) |
|
116 { |
|
117 if (aExpected === null) { |
|
118 ok(!aValue, "'" + aName + "' is null"); |
|
119 } |
|
120 else if (aValue === undefined) { |
|
121 ok(false, "'" + aName + "' is undefined"); |
|
122 } |
|
123 else if (typeof aExpected == "string" || typeof aExpected == "number" || |
|
124 typeof aExpected == "boolean") { |
|
125 is(aValue, aExpected, "property '" + aName + "'"); |
|
126 } |
|
127 else if (aExpected instanceof RegExp) { |
|
128 ok(aExpected.test(aValue), aName + ": " + aExpected + " matched " + aValue); |
|
129 } |
|
130 else if (Array.isArray(aExpected)) { |
|
131 info("checking array for property '" + aName + "'"); |
|
132 checkObject(aValue, aExpected); |
|
133 } |
|
134 else if (typeof aExpected == "object") { |
|
135 info("checking object for property '" + aName + "'"); |
|
136 checkObject(aValue, aExpected); |
|
137 } |
|
138 } |
|
139 |
|
140 function checkHeadersOrCookies(aArray, aExpected) |
|
141 { |
|
142 let foundHeaders = {}; |
|
143 |
|
144 for (let elem of aArray) { |
|
145 if (!(elem.name in aExpected)) { |
|
146 continue; |
|
147 } |
|
148 foundHeaders[elem.name] = true; |
|
149 info("checking value of header " + elem.name); |
|
150 checkValue(elem.name, elem.value, aExpected[elem.name]); |
|
151 } |
|
152 |
|
153 for (let header in aExpected) { |
|
154 if (!(header in foundHeaders)) { |
|
155 ok(false, header + " was not found"); |
|
156 } |
|
157 } |
|
158 } |
|
159 |
|
160 var gTestState = {}; |
|
161 |
|
162 function runTests(aTests, aEndCallback) |
|
163 { |
|
164 function driver() |
|
165 { |
|
166 let lastResult, sendToNext; |
|
167 for (let i = 0; i < aTests.length; i++) { |
|
168 gTestState.index = i; |
|
169 let fn = aTests[i]; |
|
170 info("will run test #" + i + ": " + fn.name); |
|
171 lastResult = fn(sendToNext, lastResult); |
|
172 sendToNext = yield lastResult; |
|
173 } |
|
174 yield aEndCallback(sendToNext, lastResult); |
|
175 } |
|
176 gTestState.driver = driver(); |
|
177 return gTestState.driver.next(); |
|
178 } |
|
179 |
|
180 function nextTest(aMessage) |
|
181 { |
|
182 return gTestState.driver.send(aMessage); |
|
183 } |