Mercurial > hg > config
comparison chrome/pageloader.js @ 196:dd0018bc27de
Copy the pageloader from CVS and into a bundle format (single chrome.manifest).
author | Benjamin Smedberg <benjamin@smedbergs.us> |
---|---|
date | Wed, 21 Jul 2010 15:57:39 -0400 |
parents | |
children | b4da709724e1 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 196:dd0018bc27de |
---|---|
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | |
2 /* ***** BEGIN LICENSE BLOCK ***** | |
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | |
4 * | |
5 * The contents of this file are subject to the Mozilla Public License Version | |
6 * 1.1 (the "License"); you may not use this file except in compliance with | |
7 * the License. You may obtain a copy of the License at | |
8 * http://www.mozilla.org/MPL/ | |
9 * | |
10 * Software distributed under the License is distributed on an "AS IS" basis, | |
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
12 * for the specific language governing rights and limitations under the | |
13 * License. | |
14 * | |
15 * The Original Code is tp. | |
16 * | |
17 * The Initial Developer of the Original Code is | |
18 * Mozilla Corporation. | |
19 * Portions created by the Initial Developer are Copyright (C) 2007 | |
20 * the Initial Developer. All Rights Reserved. | |
21 * | |
22 * Contributor(s): | |
23 * Rob Helmer <rhelmer@mozilla.com> | |
24 * Vladimir Vukicevic <vladimir@mozilla.com> | |
25 * | |
26 * Alternatively, the contents of this file may be used under the terms of | |
27 * either the GNU General Public License Version 2 or later (the "GPL"), or | |
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | |
29 * in which case the provisions of the GPL or the LGPL are applicable instead | |
30 * of those above. If you wish to allow use of your version of this file only | |
31 * under the terms of either the GPL or the LGPL, and not to allow others to | |
32 * use your version of this file under the terms of the MPL, indicate your | |
33 * decision by deleting the provisions above and replace them with the notice | |
34 * and other provisions required by the GPL or the LGPL. If you do not delete | |
35 * the provisions above, a recipient may use your version of this file under | |
36 * the terms of any one of the MPL, the GPL or the LGPL. | |
37 * | |
38 * ***** END LICENSE BLOCK ***** */ | |
39 | |
40 const Cc = Components.classes; | |
41 const Ci = Components.interfaces; | |
42 | |
43 var NUM_CYCLES = 5; | |
44 | |
45 var pageFilterRegexp = null; | |
46 var reportFormat = "js"; | |
47 var useBrowser = true; | |
48 var winWidth = 1024; | |
49 var winHeight = 768; | |
50 | |
51 var doRenderTest = false; | |
52 | |
53 var pages; | |
54 var pageIndex; | |
55 var start_time; | |
56 var cycle; | |
57 var report; | |
58 var renderReport; | |
59 var noisy = false; | |
60 var timeout = -1; | |
61 var timeoutEvent = -1; | |
62 var running = false; | |
63 var forceCC = true; | |
64 | |
65 var content; | |
66 | |
67 var TEST_DOES_OWN_TIMING = 1; | |
68 | |
69 var browserWindow = null; | |
70 | |
71 // the io service | |
72 var gIOS = null; | |
73 | |
74 function plInit() { | |
75 if (running) { | |
76 return; | |
77 } | |
78 running = true; | |
79 | |
80 cycle = 0; | |
81 | |
82 try { | |
83 var args = window.arguments[0].wrappedJSObject; | |
84 | |
85 var manifestURI = args.manifest; | |
86 var startIndex = 0; | |
87 var endIndex = -1; | |
88 if (args.startIndex) startIndex = parseInt(args.startIndex); | |
89 if (args.endIndex) endIndex = parseInt(args.endIndex); | |
90 if (args.numCycles) NUM_CYCLES = parseInt(args.numCycles); | |
91 if (args.format) reportFormat = args.format; | |
92 if (args.width) winWidth = parseInt(args.width); | |
93 if (args.height) winHeight = parseInt(args.height); | |
94 if (args.filter) pageFilterRegexp = new RegExp(args.filter); | |
95 if (args.noisy) noisy = true; | |
96 if (args.timeout) timeout = parseInt(args.timeout); | |
97 forceCC = !args.noForceCC; | |
98 doRenderTest = args.doRender; | |
99 | |
100 if (forceCC && | |
101 !window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) | |
102 .getInterface(Components.interfaces.nsIDOMWindowUtils) | |
103 .garbageCollect) { | |
104 forceCC = false; | |
105 } | |
106 | |
107 gIOS = Cc["@mozilla.org/network/io-service;1"] | |
108 .getService(Ci.nsIIOService); | |
109 if (args.offline) | |
110 gIOS.offline = true; | |
111 var fileURI = gIOS.newURI(manifestURI, null, null); | |
112 pages = plLoadURLsFromURI(fileURI); | |
113 | |
114 if (!pages) { | |
115 dumpLine('tp: could not load URLs, quitting'); | |
116 plStop(true); | |
117 } | |
118 | |
119 if (pages.length == 0) { | |
120 dumpLine('tp: no pages to test, quitting'); | |
121 plStop(true); | |
122 } | |
123 | |
124 if (startIndex < 0) | |
125 startIndex = 0; | |
126 if (endIndex == -1 || endIndex >= pages.length) | |
127 endIndex = pages.length-1; | |
128 if (startIndex > endIndex) { | |
129 dumpLine("tp: error: startIndex >= endIndex"); | |
130 plStop(true); | |
131 } | |
132 | |
133 pages = pages.slice(startIndex,endIndex+1); | |
134 var pageUrls = pages.map(function(p) { return p.url.spec.toString(); }); | |
135 report = new Report(pageUrls); | |
136 | |
137 if (doRenderTest) | |
138 renderReport = new Report(pageUrls); | |
139 | |
140 pageIndex = 0; | |
141 | |
142 if (args.useBrowserChrome) { | |
143 var wwatch = Cc["@mozilla.org/embedcomp/window-watcher;1"] | |
144 .getService(Ci.nsIWindowWatcher); | |
145 var blank = Cc["@mozilla.org/supports-string;1"] | |
146 .createInstance(Ci.nsISupportsString); | |
147 blank.data = "about:blank"; | |
148 browserWindow = wwatch.openWindow | |
149 (null, "chrome://browser/content/", "_blank", | |
150 "chrome,dialog=no,width=" + winWidth + ",height=" + winHeight, blank); | |
151 | |
152 // get our window out of the way | |
153 window.resizeTo(10,10); | |
154 | |
155 var browserLoadFunc = function (ev) { | |
156 browserWindow.removeEventListener('load', browserLoadFunc, true); | |
157 | |
158 // do this half a second after load, because we need to be | |
159 // able to resize the window and not have it get clobbered | |
160 // by the persisted values | |
161 setTimeout(function () { | |
162 browserWindow.resizeTo(winWidth, winHeight); | |
163 browserWindow.moveTo(0, 0); | |
164 browserWindow.focus(); | |
165 | |
166 content = browserWindow.getBrowser(); | |
167 setTimeout(plLoadPage, 100); | |
168 }, 500); | |
169 }; | |
170 | |
171 browserWindow.addEventListener('load', browserLoadFunc, true); | |
172 } else { | |
173 window.resizeTo(winWidth, winHeight); | |
174 | |
175 content = document.getElementById('contentPageloader'); | |
176 | |
177 setTimeout(plLoadPage, 250); | |
178 } | |
179 } catch(e) { | |
180 dumpLine(e); | |
181 plStop(true); | |
182 } | |
183 } | |
184 | |
185 function plPageFlags() { | |
186 return pages[pageIndex].flags; | |
187 } | |
188 | |
189 // load the current page, start timing | |
190 var removeLastAddedListener = null; | |
191 function plLoadPage() { | |
192 var pageName = pages[pageIndex].url.spec; | |
193 | |
194 if (removeLastAddedListener) | |
195 removeLastAddedListener(); | |
196 | |
197 if (plPageFlags() & TEST_DOES_OWN_TIMING) { | |
198 // if the page does its own timing, use a capturing handler | |
199 // to make sure that we can set up the function for content to call | |
200 content.addEventListener('load', plLoadHandlerCapturing, true); | |
201 removeLastAddedListener = function() { | |
202 content.removeEventListener('load', plLoadHandlerCapturing, true); | |
203 }; | |
204 } else { | |
205 // if the page doesn't do its own timing, use a bubbling handler | |
206 // to make sure that we're called after the page's own onload() handling | |
207 | |
208 // XXX we use a capturing event here too -- load events don't bubble up | |
209 // to the <browser> element. See bug 390263. | |
210 content.addEventListener('load', plLoadHandler, true); | |
211 removeLastAddedListener = function() { | |
212 content.removeEventListener('load', plLoadHandler, true); | |
213 }; | |
214 } | |
215 | |
216 if (timeout > 0) { | |
217 timeoutEvent = setTimeout('loadFail()', timeout); | |
218 } | |
219 start_time = Date.now(); | |
220 content.loadURI(pageName); | |
221 } | |
222 | |
223 function loadFail() { | |
224 var pageName = pages[pageIndex].url.spec; | |
225 dumpLine("__FAILTimeout exceeded on " + pageName + "__FAIL") | |
226 plStop(true); | |
227 } | |
228 | |
229 function plNextPage() { | |
230 if (pageIndex < pages.length-1) { | |
231 pageIndex++; | |
232 | |
233 if (forceCC) { | |
234 var tccstart = new Date(); | |
235 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) | |
236 .getInterface(Components.interfaces.nsIDOMWindowUtils) | |
237 .garbageCollect(); | |
238 var tccend = new Date(); | |
239 report.recordCCTime(tccend - tccstart); | |
240 } | |
241 | |
242 setTimeout(plLoadPage, 250); | |
243 } else { | |
244 plStop(false); | |
245 } | |
246 } | |
247 | |
248 function plRecordTime(time) { | |
249 var pageName = pages[pageIndex].url.spec; | |
250 var i = pageIndex | |
251 if (i < pages.length-1) { | |
252 i++; | |
253 } else { | |
254 i = 0; | |
255 } | |
256 var nextName = pages[i].url.spec; | |
257 report.recordTime(pageIndex, time); | |
258 if (noisy) { | |
259 dumpLine("Cycle " + (cycle+1) + ": loaded " + pageName + " (next: " + nextName + ")"); | |
260 } | |
261 } | |
262 | |
263 function plLoadHandlerCapturing(evt) { | |
264 // make sure we pick up the right load event | |
265 if (evt.type != 'load' || | |
266 evt.originalTarget.defaultView.frameElement) | |
267 return; | |
268 if (timeout > 0) { | |
269 clearTimeout(timeoutEvent); | |
270 } | |
271 | |
272 if (!(plPageFlags() & TEST_DOES_OWN_TIMING)) { | |
273 dumpLine("tp: Capturing onload handler used with page that doesn't do its own timing?"); | |
274 plStop(true); | |
275 } | |
276 | |
277 // set up the function for content to call | |
278 content.contentWindow.wrappedJSObject.tpRecordTime = function (time) { | |
279 plRecordTime(time); | |
280 setTimeout(plNextPage, 250); | |
281 }; | |
282 } | |
283 | |
284 // the onload handler | |
285 function plLoadHandler(evt) { | |
286 // make sure we pick up the right load event | |
287 if (evt.type != 'load' || | |
288 evt.originalTarget.defaultView.frameElement) | |
289 return; | |
290 if (timeout > 0) { | |
291 clearTimeout(timeoutEvent); | |
292 } | |
293 var end_time = Date.now(); | |
294 var time = (end_time - start_time); | |
295 | |
296 // does this page want to do its own timing? | |
297 // if so, we shouldn't be here | |
298 if (plPageFlags() & TEST_DOES_OWN_TIMING) { | |
299 dumpLine("tp: Bubbling onload handler used with page that does its own timing?"); | |
300 plStop(true); | |
301 } | |
302 | |
303 plRecordTime(time); | |
304 | |
305 if (doRenderTest) | |
306 runRenderTest(); | |
307 | |
308 plNextPage(); | |
309 } | |
310 | |
311 function runRenderTest() { | |
312 const redrawsPerSample = 500; | |
313 | |
314 if (!Ci.nsIDOMWindowUtils) | |
315 return; | |
316 | |
317 var win; | |
318 | |
319 if (browserWindow) | |
320 win = content.contentWindow; | |
321 else | |
322 win = window; | |
323 var wu = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); | |
324 | |
325 var start = Date.now(); | |
326 for (var j = 0; j < redrawsPerSample; j++) | |
327 wu.redraw(); | |
328 var end = Date.now(); | |
329 | |
330 renderReport.recordTime(pageIndex, end - start); | |
331 } | |
332 | |
333 function plStop(force) { | |
334 try { | |
335 if (force == false) { | |
336 pageIndex = 0; | |
337 if (cycle < NUM_CYCLES-1) { | |
338 cycle++; | |
339 setTimeout(plLoadPage, 250); | |
340 return; | |
341 } | |
342 | |
343 var formats = reportFormat.split(","); | |
344 | |
345 if (!renderReport) { | |
346 for each (var fmt in formats) | |
347 dumpLine(report.getReport(fmt)); | |
348 } | |
349 else { | |
350 dumpLine ("*************** Render report *******************"); | |
351 for each (var fmt in formats) | |
352 dumpLine(renderReport.getReport(fmt)); | |
353 } | |
354 } | |
355 } catch (e) { | |
356 dumpLine(e); | |
357 } | |
358 | |
359 if (content) | |
360 content.removeEventListener('load', plLoadHandler, true); | |
361 | |
362 goQuitApplication(); | |
363 } | |
364 | |
365 /* Returns array */ | |
366 function plLoadURLsFromURI(manifestUri) { | |
367 var fstream = Cc["@mozilla.org/network/file-input-stream;1"] | |
368 .createInstance(Ci.nsIFileInputStream); | |
369 var uriFile = manifestUri.QueryInterface(Ci.nsIFileURL); | |
370 | |
371 fstream.init(uriFile.file, -1, 0, 0); | |
372 var lstream = fstream.QueryInterface(Ci.nsILineInputStream); | |
373 | |
374 var d = []; | |
375 | |
376 var lineNo = 0; | |
377 var line = {value:null}; | |
378 var more; | |
379 do { | |
380 lineNo++; | |
381 more = lstream.readLine(line); | |
382 var s = line.value; | |
383 | |
384 // strip comments | |
385 s = s.replace(/#.*/, ''); | |
386 | |
387 // strip leading and trailing whitespace | |
388 s = s.replace(/^\s*/, '').replace(/s\*$/, ''); | |
389 | |
390 if (!s) | |
391 continue; | |
392 | |
393 var flags = 0; | |
394 var urlspec = s; | |
395 | |
396 // split on whitespace, and figure out if we have any flags | |
397 var items = s.split(/\s+/); | |
398 if (items[0] == "include") { | |
399 if (items.length != 2) { | |
400 dumpLine("tp: Error on line " + lineNo + " in " + manifestUri.spec + ": include must be followed by the manifest to include!"); | |
401 return null; | |
402 } | |
403 | |
404 var subManifest = gIOS.newURI(items[1], null, manifestUri); | |
405 if (subManifest == null) { | |
406 dumpLine("tp: invalid URI on line " + manifestUri.spec + ":" + lineNo + " : '" + line.value + "'"); | |
407 return null; | |
408 } | |
409 | |
410 var subItems = plLoadURLsFromURI(subManifest); | |
411 if (subItems == null) | |
412 return null; | |
413 d = d.concat(subItems); | |
414 } else { | |
415 if (items.length == 2) { | |
416 if (items[0].indexOf("%") != -1) | |
417 flags |= TEST_DOES_OWN_TIMING; | |
418 | |
419 urlspec = items[1]; | |
420 } else if (items.length != 1) { | |
421 dumpLine("tp: Error on line " + lineNo + " in " + manifestUri.spec + ": whitespace must be %-escaped!"); | |
422 return null; | |
423 } | |
424 | |
425 var url = gIOS.newURI(urlspec, null, manifestUri); | |
426 | |
427 if (pageFilterRegexp && !pageFilterRegexp.test(url.spec)) | |
428 continue; | |
429 | |
430 d.push({ url: url, | |
431 flags: flags }); | |
432 } | |
433 } while (more); | |
434 | |
435 return d; | |
436 } | |
437 | |
438 function dumpLine(str) { | |
439 dump(str); | |
440 dump("\n"); | |
441 } |