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 }