|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 var gBrowser; |
|
6 var gProgressListener; |
|
7 var gDebugger; |
|
8 var gRTestIndexList; |
|
9 var gRTestURLList = null; |
|
10 |
|
11 const nsILayoutDebuggingTools = Components.interfaces.nsILayoutDebuggingTools; |
|
12 const nsIDocShell = Components.interfaces.nsIDocShell; |
|
13 const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener; |
|
14 |
|
15 const NS_LAYOUT_DEBUGGINGTOOLS_CONTRACTID = "@mozilla.org/layout-debug/layout-debuggingtools;1"; |
|
16 |
|
17 |
|
18 function nsLDBBrowserContentListener() |
|
19 { |
|
20 this.init(); |
|
21 } |
|
22 |
|
23 nsLDBBrowserContentListener.prototype = { |
|
24 |
|
25 init : function() |
|
26 { |
|
27 this.mStatusText = document.getElementById("status-text"); |
|
28 this.mURLBar = document.getElementById("urlbar"); |
|
29 this.mForwardButton = document.getElementById("forward-button"); |
|
30 this.mBackButton = document.getElementById("back-button"); |
|
31 this.mStopButton = document.getElementById("stop-button"); |
|
32 }, |
|
33 |
|
34 QueryInterface : function(aIID) |
|
35 { |
|
36 if (aIID.equals(Components.interfaces.nsIWebProgressListener) || |
|
37 aIID.equals(Components.interfaces.nsISupportsWeakReference) || |
|
38 aIID.equals(Components.interfaces.nsISupports)) |
|
39 return this; |
|
40 throw Components.results.NS_NOINTERFACE; |
|
41 }, |
|
42 |
|
43 // nsIWebProgressListener implementation |
|
44 onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus) |
|
45 { |
|
46 if (!(aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) || |
|
47 aWebProgress != gBrowser.webProgress) |
|
48 return; |
|
49 |
|
50 if (aStateFlags & nsIWebProgressListener.STATE_START) { |
|
51 this.setButtonEnabled(this.mStopButton, true); |
|
52 this.setButtonEnabled(this.mForwardButton, gBrowser.canGoForward); |
|
53 this.setButtonEnabled(this.mBackButton, gBrowser.canGoBack); |
|
54 this.mStatusText.value = "loading..."; |
|
55 this.mLoading = true; |
|
56 |
|
57 } else if (aStateFlags & nsIWebProgressListener.STATE_STOP) { |
|
58 this.setButtonEnabled(this.mStopButton, false); |
|
59 this.mStatusText.value = this.mURLBar.value + " loaded"; |
|
60 |
|
61 if (gRTestURLList && this.mLoading) { |
|
62 // Let other things happen in the first 20ms, since this |
|
63 // doesn't really seem to be when the page is done loading. |
|
64 setTimeout("gRTestURLList.doneURL()", 20); |
|
65 } |
|
66 this.mLoading = false; |
|
67 } |
|
68 }, |
|
69 |
|
70 onProgressChange : function(aWebProgress, aRequest, |
|
71 aCurSelfProgress, aMaxSelfProgress, |
|
72 aCurTotalProgress, aMaxTotalProgress) |
|
73 { |
|
74 }, |
|
75 |
|
76 onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) |
|
77 { |
|
78 this.mURLBar.value = aLocation.spec; |
|
79 this.setButtonEnabled(this.mForwardButton, gBrowser.canGoForward); |
|
80 this.setButtonEnabled(this.mBackButton, gBrowser.canGoBack); |
|
81 }, |
|
82 |
|
83 onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) |
|
84 { |
|
85 this.mStatusText.value = aMessage; |
|
86 }, |
|
87 |
|
88 onSecurityChange : function(aWebProgress, aRequest, aState) |
|
89 { |
|
90 }, |
|
91 |
|
92 // non-interface methods |
|
93 setButtonEnabled : function(aButtonElement, aEnabled) |
|
94 { |
|
95 if (aEnabled) |
|
96 aButtonElement.removeAttribute("disabled"); |
|
97 else |
|
98 aButtonElement.setAttribute("disabled", "true"); |
|
99 }, |
|
100 |
|
101 mStatusText : null, |
|
102 mURLBar : null, |
|
103 mForwardButton : null, |
|
104 mBackButton : null, |
|
105 mStopButton : null, |
|
106 |
|
107 mLoading : false |
|
108 |
|
109 } |
|
110 |
|
111 function OnLDBLoad() |
|
112 { |
|
113 gBrowser = document.getElementById("browser"); |
|
114 |
|
115 gProgressListener = new nsLDBBrowserContentListener(); |
|
116 gBrowser.addProgressListener(gProgressListener); |
|
117 |
|
118 gDebugger = Components.classes[NS_LAYOUT_DEBUGGINGTOOLS_CONTRACTID]. |
|
119 createInstance(nsILayoutDebuggingTools); |
|
120 |
|
121 if (window.arguments && window.arguments[0]) |
|
122 gBrowser.loadURI(window.arguments[0]); |
|
123 else |
|
124 gBrowser.goHome(); |
|
125 |
|
126 gDebugger.init(gBrowser.contentWindow); |
|
127 |
|
128 checkPersistentMenus(); |
|
129 gRTestIndexList = new RTestIndexList(); |
|
130 } |
|
131 |
|
132 function checkPersistentMenu(item) |
|
133 { |
|
134 var menuitem = document.getElementById("menu_" + item); |
|
135 menuitem.setAttribute("checked", gDebugger[item]); |
|
136 } |
|
137 |
|
138 function checkPersistentMenus() |
|
139 { |
|
140 // Restore the toggles that are stored in prefs. |
|
141 checkPersistentMenu("paintFlashing"); |
|
142 checkPersistentMenu("paintDumping"); |
|
143 checkPersistentMenu("invalidateDumping"); |
|
144 checkPersistentMenu("eventDumping"); |
|
145 checkPersistentMenu("motionEventDumping"); |
|
146 checkPersistentMenu("crossingEventDumping"); |
|
147 checkPersistentMenu("reflowCounts"); |
|
148 } |
|
149 |
|
150 |
|
151 function OnLDBUnload() |
|
152 { |
|
153 gBrowser.removeProgressListener(gProgressListener); |
|
154 } |
|
155 |
|
156 function toggle(menuitem) |
|
157 { |
|
158 // trim the initial "menu_" |
|
159 var feature = menuitem.id.substring(5); |
|
160 gDebugger[feature] = menuitem.getAttribute("checked") == "true"; |
|
161 } |
|
162 |
|
163 function openFile() |
|
164 { |
|
165 var nsIFilePicker = Components.interfaces.nsIFilePicker; |
|
166 var fp = Components.classes["@mozilla.org/filepicker;1"] |
|
167 .createInstance(nsIFilePicker); |
|
168 fp.init(window, "Select a File", nsIFilePicker.modeOpen); |
|
169 fp.appendFilters(nsIFilePicker.filterHTML | nsIFilePicker.filterAll); |
|
170 if (fp.show() == nsIFilePicker.returnOK && fp.fileURL.spec && |
|
171 fp.fileURL.spec.length > 0) { |
|
172 gBrowser.loadURI(fp.fileURL.spec); |
|
173 } |
|
174 } |
|
175 const LDB_RDFNS = "http://mozilla.org/newlayout/LDB-rdf#"; |
|
176 const NC_RDFNS = "http://home.netscape.com/NC-rdf#"; |
|
177 |
|
178 function RTestIndexList() { |
|
179 this.init(); |
|
180 } |
|
181 |
|
182 RTestIndexList.prototype = { |
|
183 |
|
184 init : function() |
|
185 { |
|
186 const nsIPrefService = Components.interfaces.nsIPrefService; |
|
187 const PREF_SERVICE_CONTRACTID = "@mozilla.org/preferences-service;1"; |
|
188 const PREF_BRANCH_NAME = "layout_debugger.rtest_url."; |
|
189 const nsIRDFService = Components.interfaces.nsIRDFService; |
|
190 const RDF_SERVICE_CONTRACTID = "@mozilla.org/rdf/rdf-service;1"; |
|
191 const nsIRDFDataSource = Components.interfaces.nsIRDFDataSource; |
|
192 const RDF_DATASOURCE_CONTRACTID = |
|
193 "@mozilla.org/rdf/datasource;1?name=in-memory-datasource"; |
|
194 |
|
195 this.mPrefService = Components.classes[PREF_SERVICE_CONTRACTID]. |
|
196 getService(nsIPrefService); |
|
197 this.mPrefBranch = this.mPrefService.getBranch(PREF_BRANCH_NAME); |
|
198 |
|
199 this.mRDFService = Components.classes[RDF_SERVICE_CONTRACTID]. |
|
200 getService(nsIRDFService); |
|
201 this.mDataSource = Components.classes[RDF_DATASOURCE_CONTRACTID]. |
|
202 createInstance(nsIRDFDataSource); |
|
203 |
|
204 this.mLDB_Root = this.mRDFService.GetResource(LDB_RDFNS + "Root"); |
|
205 this.mNC_Name = this.mRDFService.GetResource(NC_RDFNS + "name"); |
|
206 this.mNC_Child = this.mRDFService.GetResource(NC_RDFNS + "child"); |
|
207 |
|
208 this.load(); |
|
209 |
|
210 document.getElementById("menu_RTest_baseline").database. |
|
211 AddDataSource(this.mDataSource); |
|
212 document.getElementById("menu_RTest_verify").database. |
|
213 AddDataSource(this.mDataSource); |
|
214 document.getElementById("menu_RTest_remove").database. |
|
215 AddDataSource(this.mDataSource); |
|
216 }, |
|
217 |
|
218 save : function() |
|
219 { |
|
220 this.mPrefBranch.deleteBranch(""); |
|
221 |
|
222 const nsIRDFLiteral = Components.interfaces.nsIRDFLiteral; |
|
223 const nsIRDFResource = Components.interfaces.nsIRDFResource; |
|
224 var etor = this.mDataSource.GetTargets(this.mLDB_Root, |
|
225 this.mNC_Child, true); |
|
226 var i = 0; |
|
227 while (etor.hasMoreElements()) { |
|
228 var resource = etor.getNext().QueryInterface(nsIRDFResource); |
|
229 var literal = this.mDataSource.GetTarget(resource, this.mNC_Name, true); |
|
230 literal = literal.QueryInterface(nsIRDFLiteral); |
|
231 this.mPrefBranch.setCharPref(i.toString(), literal.Value); |
|
232 ++i; |
|
233 } |
|
234 |
|
235 this.mPrefService.savePrefFile(null); |
|
236 }, |
|
237 |
|
238 load : function() |
|
239 { |
|
240 var prefList = this.mPrefBranch.getChildList(""); |
|
241 |
|
242 var i = 0; |
|
243 for (var pref in prefList) { |
|
244 var file = this.mPrefBranch.getCharPref(pref); |
|
245 var resource = this.mRDFService.GetResource(file); |
|
246 var literal = this.mRDFService.GetLiteral(file); |
|
247 this.mDataSource.Assert(this.mLDB_Root, this.mNC_Child, resource, true); |
|
248 this.mDataSource.Assert(resource, this.mNC_Name, literal, true); |
|
249 ++i; |
|
250 } |
|
251 |
|
252 }, |
|
253 |
|
254 /* Add a new list of regression tests to the menus. */ |
|
255 add : function() |
|
256 { |
|
257 const nsIFilePicker = Components.interfaces.nsIFilePicker; |
|
258 const NS_FILEPICKER_CONTRACTID = "@mozilla.org/filepicker;1"; |
|
259 |
|
260 var fp = Components.classes[NS_FILEPICKER_CONTRACTID]. |
|
261 createInstance(nsIFilePicker); |
|
262 |
|
263 // XXX l10n (but this is just for 5 developers, so no problem) |
|
264 fp.init(window, "New Regression Test List", nsIFilePicker.modeOpen); |
|
265 fp.appendFilters(nsIFilePicker.filterAll); |
|
266 fp.defaultString = "rtest.lst"; |
|
267 if (fp.show() != nsIFilePicker.returnOK) |
|
268 return; |
|
269 |
|
270 var file = fp.file.persistentDescriptor; |
|
271 var resource = this.mRDFService.GetResource(file); |
|
272 var literal = this.mRDFService.GetLiteral(file); |
|
273 this.mDataSource.Assert(this.mLDB_Root, this.mNC_Child, resource, true); |
|
274 this.mDataSource.Assert(resource, this.mNC_Name, literal, true); |
|
275 |
|
276 this.save(); |
|
277 |
|
278 }, |
|
279 |
|
280 remove : function(file) |
|
281 { |
|
282 var resource = this.mRDFService.GetResource(file); |
|
283 var literal = this.mRDFService.GetLiteral(file); |
|
284 this.mDataSource.Unassert(this.mLDB_Root, this.mNC_Child, resource); |
|
285 this.mDataSource.Unassert(resource, this.mNC_Name, literal); |
|
286 |
|
287 this.save(); |
|
288 }, |
|
289 |
|
290 mPrefBranch : null, |
|
291 mPrefService : null, |
|
292 mRDFService : null, |
|
293 mDataSource : null, |
|
294 mLDB_Root : null, |
|
295 mNC_Child : null, |
|
296 mNC_Name : null |
|
297 } |
|
298 |
|
299 const nsIFileInputStream = Components.interfaces.nsIFileInputStream; |
|
300 const nsILineInputStream = Components.interfaces.nsILineInputStream; |
|
301 const nsIFile = Components.interfaces.nsIFile; |
|
302 const nsILocalFile = Components.interfaces.nsILocalFile; |
|
303 const nsIFileURL = Components.interfaces.nsIFileURL; |
|
304 const nsIIOService = Components.interfaces.nsIIOService; |
|
305 const nsILayoutRegressionTester = Components.interfaces.nsILayoutRegressionTester; |
|
306 |
|
307 const NS_LOCAL_FILE_CONTRACTID = "@mozilla.org/file/local;1"; |
|
308 const IO_SERVICE_CONTRACTID = "@mozilla.org/network/io-service;1"; |
|
309 const NS_LOCALFILEINPUTSTREAM_CONTRACTID = |
|
310 "@mozilla.org/network/file-input-stream;1"; |
|
311 |
|
312 |
|
313 function RunRTest(aFilename, aIsBaseline, aIsPrinting) |
|
314 { |
|
315 if (gRTestURLList) { |
|
316 // XXX Does alert work? |
|
317 alert("Already running regression test.\n"); |
|
318 return; |
|
319 } |
|
320 dump("Running " + (aIsBaseline?"baseline":"verify") + |
|
321 (aIsPrinting?" PrintMode":"") + " test for " + aFilename + ".\n"); |
|
322 |
|
323 var listFile = Components.classes[NS_LOCAL_FILE_CONTRACTID]. |
|
324 createInstance(nsILocalFile); |
|
325 listFile.persistentDescriptor = aFilename; |
|
326 gRTestURLList = new RTestURLList(listFile, aIsBaseline, aIsPrinting); |
|
327 gRTestURLList.startURL(); |
|
328 } |
|
329 |
|
330 function RTestURLList(aLocalFile, aIsBaseline, aIsPrinting) { |
|
331 this.init(aLocalFile, aIsBaseline, aIsPrinting); |
|
332 } |
|
333 |
|
334 RTestURLList.prototype = { |
|
335 init : function(aLocalFile, aIsBaseline, aIsPrinting) |
|
336 { |
|
337 this.mIsBaseline = aIsBaseline; |
|
338 this.mIsPrinting = aIsPrinting; |
|
339 this.mURLs = new Array(); |
|
340 this.readFileList(aLocalFile); |
|
341 this.mRegressionTester = |
|
342 Components.classes["@mozilla.org/layout-debug/regressiontester;1"]. |
|
343 createInstance(nsILayoutRegressionTester) |
|
344 }, |
|
345 |
|
346 readFileList : function(aLocalFile) |
|
347 { |
|
348 var ios = Components.classes[IO_SERVICE_CONTRACTID] |
|
349 .getService(nsIIOService); |
|
350 var dirURL = ios.newFileURI(aLocalFile.parent); |
|
351 |
|
352 var fis = Components.classes[NS_LOCALFILEINPUTSTREAM_CONTRACTID]. |
|
353 createInstance(nsIFileInputStream); |
|
354 fis.init(aLocalFile, -1, -1, false); |
|
355 var lis = fis.QueryInterface(nsILineInputStream); |
|
356 |
|
357 var line = {value:null}; |
|
358 do { |
|
359 var more = lis.readLine(line); |
|
360 var str = line.value; |
|
361 str = /^[^#]*/.exec(str); // strip everything after "#" |
|
362 str = /\S*/.exec(str); // take the first chunk of non-whitespace |
|
363 if (!str || str == "") |
|
364 continue; |
|
365 |
|
366 var item = dirURL.resolve(str); |
|
367 if (item.match(/\/rtest.lst$/)) { |
|
368 var itemurl = ios.newURI(item, null, null); |
|
369 itemurl = itemurl.QueryInterface(nsIFileURL); |
|
370 this.readFileList(itemurl.file); |
|
371 } else { |
|
372 this.mURLs.push( {url:item, dir:aLocalFile.parent, relurl:str} ); |
|
373 } |
|
374 } while (more); |
|
375 }, |
|
376 |
|
377 doneURL : function() |
|
378 { |
|
379 var basename = |
|
380 String(this.mCurrentURL.relurl).replace(/[:=&.\/?]/g, "_") + ".rgd"; |
|
381 |
|
382 var data = this.mCurrentURL.dir.clone(); |
|
383 data.append( this.mIsBaseline ? "baseline" : "verify"); |
|
384 if (!data.exists()) |
|
385 data.create(nsIFile.DIRECTORY_TYPE, 0777) |
|
386 data.append(basename); |
|
387 |
|
388 dump("Writing regression data to " + |
|
389 data.QueryInterface(nsILocalFile).persistentDescriptor + "\n"); |
|
390 if (this.mIsPrinting) { |
|
391 this.mRegressionTester.dumpFrameModel(gBrowser.contentWindow, data, |
|
392 nsILayoutRegressionTester.DUMP_FLAGS_MASK_PRINT_MODE); |
|
393 } |
|
394 else { |
|
395 this.mRegressionTester.dumpFrameModel(gBrowser.contentWindow, data, 0); |
|
396 } |
|
397 |
|
398 |
|
399 |
|
400 if (!this.mIsBaseline) { |
|
401 var base_data = this.mCurrentURL.dir.clone(); |
|
402 base_data.append("baseline"); |
|
403 base_data.append(basename); |
|
404 dump("Comparing to regression data from " + |
|
405 base_data.QueryInterface(nsILocalFile).persistentDescriptor + "\n"); |
|
406 var filesDiffer = |
|
407 this.mRegressionTester.compareFrameModels(base_data, data, |
|
408 nsILayoutRegressionTester.COMPARE_FLAGS_BRIEF) |
|
409 dump("Comparison for " + this.mCurrentURL.url + " " + |
|
410 (filesDiffer ? "failed" : "passed") + ".\n"); |
|
411 } |
|
412 |
|
413 this.mCurrentURL = null; |
|
414 |
|
415 this.startURL(); |
|
416 }, |
|
417 |
|
418 startURL : function() |
|
419 { |
|
420 this.mCurrentURL = this.mURLs.shift(); |
|
421 if (!this.mCurrentURL) { |
|
422 gRTestURLList = null; |
|
423 return; |
|
424 } |
|
425 |
|
426 gBrowser.loadURI(this.mCurrentURL.url); |
|
427 }, |
|
428 |
|
429 mURLs : null, |
|
430 mCurrentURL : null, // url (string), dir (nsIFileURL), relurl (string) |
|
431 mIsBaseline : null, |
|
432 mRegressionTester : null, |
|
433 mIsPrinting : null |
|
434 } |