layout/tools/layout-debug/ui/content/layoutdebug.js

changeset 2
7e26c7da4463
equal deleted inserted replaced
-1:000000000000 0:8d99966d0129
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 }

mercurial