Mercurial > hg > config
comparison chrome/pageloader.js @ 208:3f290bcae11a
wtf
author | Jeff Hammel <jhammel@mozilla.com> |
---|---|
date | Mon, 13 Feb 2012 16:24:06 -0800 |
parents | beca399c3a16 |
children |
comparison
equal
deleted
inserted
replaced
207:7bad4b7281f2 | 208:3f290bcae11a |
---|---|
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 try { | |
41 if (Cc === undefined) { | |
42 var Cc = Components.classes; | |
43 var Ci = Components.interfaces; | |
44 } | |
45 } catch (ex) {} | |
46 | |
47 var NUM_CYCLES = 5; | |
48 | |
49 var pageFilterRegexp = null; | |
50 var reportFormat = "js"; | |
51 var useBrowser = true; | |
52 var winWidth = 1024; | |
53 var winHeight = 768; | |
54 | |
55 var doRenderTest = false; | |
56 | |
57 var pages; | |
58 var pageIndex; | |
59 var start_time; | |
60 var cycle; | |
61 var report; | |
62 var renderReport; | |
63 var noisy = false; | |
64 var timeout = -1; | |
65 var delay = 250; | |
66 var timeoutEvent = -1; | |
67 var running = false; | |
68 var forceCC = true; | |
69 var reportRSS = false; | |
70 | |
71 var useMozAfterPaint = false; | |
72 var gPaintWindow = window; | |
73 var gPaintListener = false; | |
74 | |
75 //when TEST_DOES_OWN_TIMING, we need to store the time from the page as MozAfterPaint can be slower than pageload | |
76 var gTime = -1; | |
77 var gStartTime = -1; | |
78 | |
79 var content; | |
80 | |
81 var TEST_DOES_OWN_TIMING = 1; | |
82 | |
83 var browserWindow = null; | |
84 | |
85 // the io service | |
86 var gIOS = null; | |
87 | |
88 function plInit() { | |
89 if (running) { | |
90 return; | |
91 } | |
92 running = true; | |
93 | |
94 cycle = 0; | |
95 | |
96 try { | |
97 var args = window.arguments[0].wrappedJSObject; | |
98 | |
99 var manifestURI = args.manifest; | |
100 var startIndex = 0; | |
101 var endIndex = -1; | |
102 if (args.startIndex) startIndex = parseInt(args.startIndex); | |
103 if (args.endIndex) endIndex = parseInt(args.endIndex); | |
104 if (args.numCycles) NUM_CYCLES = parseInt(args.numCycles); | |
105 if (args.format) reportFormat = args.format; | |
106 if (args.width) winWidth = parseInt(args.width); | |
107 if (args.height) winHeight = parseInt(args.height); | |
108 if (args.filter) pageFilterRegexp = new RegExp(args.filter); | |
109 if (args.noisy) noisy = true; | |
110 if (args.timeout) timeout = parseInt(args.timeout); | |
111 if (args.delay) delay = parseInt(args.delay); | |
112 if (args.mozafterpaint) useMozAfterPaint = true; | |
113 if (args.rss) reportRSS = true; | |
114 | |
115 forceCC = !args.noForceCC; | |
116 doRenderTest = args.doRender; | |
117 | |
118 if (forceCC && | |
119 !window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) | |
120 .getInterface(Components.interfaces.nsIDOMWindowUtils) | |
121 .garbageCollect) { | |
122 forceCC = false; | |
123 } | |
124 | |
125 gIOS = Cc["@mozilla.org/network/io-service;1"] | |
126 .getService(Ci.nsIIOService); | |
127 if (args.offline) | |
128 gIOS.offline = true; | |
129 var fileURI = gIOS.newURI(manifestURI, null, null); | |
130 pages = plLoadURLsFromURI(fileURI); | |
131 | |
132 if (!pages) { | |
133 dumpLine('tp: could not load URLs, quitting'); | |
134 plStop(true); | |
135 } | |
136 | |
137 if (pages.length == 0) { | |
138 dumpLine('tp: no pages to test, quitting'); | |
139 plStop(true); | |
140 } | |
141 | |
142 if (startIndex < 0) | |
143 startIndex = 0; | |
144 if (endIndex == -1 || endIndex >= pages.length) | |
145 endIndex = pages.length-1; | |
146 if (startIndex > endIndex) { | |
147 dumpLine("tp: error: startIndex >= endIndex"); | |
148 plStop(true); | |
149 } | |
150 | |
151 pages = pages.slice(startIndex,endIndex+1); | |
152 var pageUrls = pages.map(function(p) { return p.url.spec.toString(); }); | |
153 report = new Report(pageUrls); | |
154 | |
155 if (doRenderTest) | |
156 renderReport = new Report(pageUrls); | |
157 | |
158 pageIndex = 0; | |
159 | |
160 if (args.useBrowserChrome) { | |
161 var wwatch = Cc["@mozilla.org/embedcomp/window-watcher;1"] | |
162 .getService(Ci.nsIWindowWatcher); | |
163 var blank = Cc["@mozilla.org/supports-string;1"] | |
164 .createInstance(Ci.nsISupportsString); | |
165 blank.data = "about:blank"; | |
166 browserWindow = wwatch.openWindow | |
167 (null, "chrome://browser/content/", "_blank", | |
168 "chrome,all,dialog=no,width=" + winWidth + ",height=" + winHeight, blank); | |
169 | |
170 gPaintWindow = browserWindow; | |
171 // get our window out of the way | |
172 window.resizeTo(10,10); | |
173 | |
174 var browserLoadFunc = function (ev) { | |
175 browserWindow.removeEventListener('load', browserLoadFunc, true); | |
176 | |
177 // do this half a second after load, because we need to be | |
178 // able to resize the window and not have it get clobbered | |
179 // by the persisted values | |
180 setTimeout(function () { | |
181 browserWindow.resizeTo(winWidth, winHeight); | |
182 browserWindow.moveTo(0, 0); | |
183 browserWindow.focus(); | |
184 | |
185 content = browserWindow.getBrowser(); | |
186 | |
187 // Load the frame script for e10s / IPC message support | |
188 if (content.getAttribute("remote") == "true") { | |
189 let contentScript = "data:,function _contentLoadHandler(e) { " + | |
190 " if (e.originalTarget.defaultView == content) { " + | |
191 " content.wrappedJSObject.tpRecordTime = function(t, s) { sendAsyncMessage('PageLoader:RecordTime', { time: t, startTime: s }); }; "; | |
192 if (useMozAfterPaint) { | |
193 contentScript += "" + | |
194 "function _contentPaintHandler() { " + | |
195 " var utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils); " + | |
196 " if (utils.isMozAfterPaintPending) { " + | |
197 " addEventListener('MozAfterPaint', function(e) { " + | |
198 " removeEventListener('MozAfterPaint', arguments.callee, true); " + | |
199 " sendAsyncMessage('PageLoader:MozAfterPaint', {}); " + | |
200 " }, true); " + | |
201 " } else { " + | |
202 " sendAsyncMessage('PageLoader:MozAfterPaint', {}); " + | |
203 " } " + | |
204 "}; " + | |
205 "content.wrappedJSObject.setTimeout(_contentPaintHandler, 0); "; | |
206 } else { | |
207 contentScript += " sendAsyncMessage('PageLoader:Load', {}); "; | |
208 } | |
209 contentScript += "" + | |
210 " }" + | |
211 "} " + | |
212 "addEventListener('load', _contentLoadHandler, true); "; | |
213 content.messageManager.loadFrameScript(contentScript, false); | |
214 } | |
215 if (reportRSS) { | |
216 initializeMemoryCollector(plLoadPage, 100); | |
217 } else { | |
218 setTimeout(plLoadPage, 100); | |
219 } | |
220 }, 500); | |
221 }; | |
222 | |
223 browserWindow.addEventListener('load', browserLoadFunc, true); | |
224 } else { | |
225 gPaintWindow = window; | |
226 window.resizeTo(winWidth, winHeight); | |
227 | |
228 content = document.getElementById('contentPageloader'); | |
229 | |
230 if (reportRSS) { | |
231 initializeMemoryCollector(plLoadPage, delay); | |
232 } else { | |
233 setTimeout(plLoadPage, delay); | |
234 } | |
235 } | |
236 } catch(e) { | |
237 dumpLine(e); | |
238 plStop(true); | |
239 } | |
240 } | |
241 | |
242 function plPageFlags() { | |
243 return pages[pageIndex].flags; | |
244 } | |
245 | |
246 // load the current page, start timing | |
247 var removeLastAddedListener = null; | |
248 var removeLastAddedMsgListener = null; | |
249 function plLoadPage() { | |
250 var pageName = pages[pageIndex].url.spec; | |
251 | |
252 if (removeLastAddedListener) | |
253 removeLastAddedListener(); | |
254 | |
255 if (removeLastAddedMsgListener) | |
256 removeLastAddedMsgListener(); | |
257 | |
258 if (plPageFlags() & TEST_DOES_OWN_TIMING) { | |
259 // if the page does its own timing, use a capturing handler | |
260 // to make sure that we can set up the function for content to call | |
261 | |
262 content.addEventListener('load', plLoadHandlerCapturing, true); | |
263 removeLastAddedListener = function() { | |
264 content.removeEventListener('load', plLoadHandlerCapturing, true); | |
265 if (useMozAfterPaint) { | |
266 content.removeEventListener("MozAfterPaint", plPaintedCapturing, true); | |
267 gPaintHandler = false; | |
268 } | |
269 }; | |
270 } else { | |
271 // if the page doesn't do its own timing, use a bubbling handler | |
272 // to make sure that we're called after the page's own onload() handling | |
273 | |
274 // XXX we use a capturing event here too -- load events don't bubble up | |
275 // to the <browser> element. See bug 390263. | |
276 content.addEventListener('load', plLoadHandler, true); | |
277 removeLastAddedListener = function() { | |
278 content.removeEventListener('load', plLoadHandler, true); | |
279 if (useMozAfterPaint) { | |
280 gPaintWindow.removeEventListener("MozAfterPaint", plPainted, true); | |
281 gPaintHandler = false; | |
282 } | |
283 }; | |
284 } | |
285 | |
286 // If the test browser is remote (e10s / IPC) we need to use messages to watch for page load | |
287 if (content.getAttribute("remote") == "true") { | |
288 content.messageManager.addMessageListener('PageLoader:Load', plLoadHandlerMessage); | |
289 content.messageManager.addMessageListener('PageLoader:RecordTime', plRecordTimeMessage); | |
290 if (useMozAfterPaint) | |
291 content.messageManager.addMessageListener('PageLoader:MozAfterPaint', plPaintHandler); | |
292 removeLastAddedMsgListener = function() { | |
293 content.messageManager.removeMessageListener('PageLoader:Load', plLoadHandlerMessage); | |
294 content.messageManager.removeMessageListener('PageLoader:RecordTime', plRecordTimeMessage); | |
295 if (useMozAfterPaint) | |
296 content.messageManager.removeMessageListener('PageLoader:MozAfterPaint', plPaintHandler); | |
297 }; | |
298 } | |
299 | |
300 if (timeout > 0) { | |
301 timeoutEvent = setTimeout('loadFail()', timeout); | |
302 } | |
303 if (reportRSS) { | |
304 collectMemory(startAndLoadURI, pageName); | |
305 } else { | |
306 startAndLoadURI(pageName); | |
307 } | |
308 } | |
309 | |
310 function startAndLoadURI(pageName) { | |
311 start_time = Date.now(); | |
312 content.loadURI(pageName); | |
313 } | |
314 | |
315 function loadFail() { | |
316 var pageName = pages[pageIndex].url.spec; | |
317 dumpLine("__FAILTimeout exceeded on " + pageName + "__FAIL") | |
318 plStop(true); | |
319 } | |
320 | |
321 function plNextPage() { | |
322 if (pageIndex < pages.length-1) { | |
323 pageIndex++; | |
324 | |
325 if (forceCC) { | |
326 var tccstart = new Date(); | |
327 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) | |
328 .getInterface(Components.interfaces.nsIDOMWindowUtils) | |
329 .garbageCollect(); | |
330 var tccend = new Date(); | |
331 report.recordCCTime(tccend - tccstart); | |
332 } | |
333 | |
334 setTimeout(plLoadPage, delay); | |
335 } else { | |
336 plStop(false); | |
337 } | |
338 } | |
339 | |
340 function plRecordTime(time) { | |
341 var pageName = pages[pageIndex].url.spec; | |
342 var i = pageIndex | |
343 if (i < pages.length-1) { | |
344 i++; | |
345 } else { | |
346 i = 0; | |
347 } | |
348 var nextName = pages[i].url.spec; | |
349 report.recordTime(pageIndex, time); | |
350 if (noisy) { | |
351 dumpLine("Cycle " + (cycle+1) + ": loaded " + pageName + " (next: " + nextName + ")"); | |
352 } | |
353 } | |
354 | |
355 function plLoadHandlerCapturing(evt) { | |
356 // make sure we pick up the right load event | |
357 if (evt.type != 'load' || | |
358 evt.originalTarget.defaultView.frameElement) | |
359 return; | |
360 | |
361 //set the tpRecordTime function (called from test pages we load to store a global time. | |
362 content.contentWindow.wrappedJSObject.tpRecordTime = function (time, startTime) { | |
363 gTime = time; | |
364 gStartTime = startTime; | |
365 setTimeout(plWaitForPaintingCapturing, 0); | |
366 } | |
367 | |
368 content.removeEventListener('load', plLoadHandlerCapturing, true); | |
369 | |
370 setTimeout(plWaitForPaintingCapturing, 0); | |
371 } | |
372 | |
373 function plWaitForPaintingCapturing() { | |
374 if (gPaintListener) | |
375 return; | |
376 | |
377 var utils = gPaintWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor) | |
378 .getInterface(Components.interfaces.nsIDOMWindowUtils); | |
379 | |
380 if (utils.isMozAfterPaintPending && useMozAfterPaint) { | |
381 if (gPaintListener == false) | |
382 gPaintWindow.addEventListener("MozAfterPaint", plPaintedCapturing, true); | |
383 gPaintListener = true; | |
384 return; | |
385 } | |
386 | |
387 _loadHandlerCapturing(); | |
388 } | |
389 | |
390 function plPaintedCapturing() { | |
391 gPaintWindow.removeEventListener("MozAfterPaint", plPaintedCapturing, true); | |
392 gPaintListener = false; | |
393 _loadHandlerCapturing(); | |
394 } | |
395 | |
396 function _loadHandlerCapturing() { | |
397 if (timeout > 0) { | |
398 clearTimeout(timeoutEvent); | |
399 } | |
400 | |
401 if (!(plPageFlags() & TEST_DOES_OWN_TIMING)) { | |
402 dumpLine("tp: Capturing onload handler used with page that doesn't do its own timing?"); | |
403 plStop(true); | |
404 } | |
405 | |
406 if (useMozAfterPaint) { | |
407 if (gStartTime != null && gStartTime >= 0) { | |
408 gTime = (new Date()) - gStartTime; | |
409 gStartTime = -1; | |
410 } | |
411 } | |
412 | |
413 // set up the function for content to call | |
414 if (gTime >= 0) { | |
415 plRecordTime(gTime); | |
416 gTime = -1; | |
417 setTimeout(plNextPage, delay); | |
418 }; | |
419 } | |
420 | |
421 // the onload handler | |
422 function plLoadHandler(evt) { | |
423 // make sure we pick up the right load event | |
424 if (evt.type != 'load' || | |
425 evt.originalTarget.defaultView.frameElement) | |
426 return; | |
427 | |
428 content.removeEventListener('load', plLoadHandler, true); | |
429 setTimeout(waitForPainted, 0); | |
430 } | |
431 | |
432 // This is called after we have received a load event, now we wait for painted | |
433 function waitForPainted() { | |
434 | |
435 var utils = gPaintWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor) | |
436 .getInterface(Components.interfaces.nsIDOMWindowUtils); | |
437 | |
438 if (!utils.isMozAfterPaintPending || !useMozAfterPaint) { | |
439 _loadHandler(); | |
440 return; | |
441 } | |
442 | |
443 if (gPaintListener == false) | |
444 gPaintWindow.addEventListener("MozAfterPaint", plPainted, true); | |
445 gPaintListener = true; | |
446 } | |
447 | |
448 function plPainted() { | |
449 gPaintWindow.removeEventListener("MozAfterPaint", plPainted, true); | |
450 gPaintListener = false; | |
451 _loadHandler(); | |
452 } | |
453 | |
454 function _loadHandler() { | |
455 if (timeout > 0) { | |
456 clearTimeout(timeoutEvent); | |
457 } | |
458 var docElem; | |
459 if (browserWindow) | |
460 docElem = browserWindow.frames["content"].document.documentElement; | |
461 else | |
462 docElem = content.contentDocument.documentElement; | |
463 var width; | |
464 if ("getBoundingClientRect" in docElem) { | |
465 width = docElem.getBoundingClientRect().width; | |
466 } else if ("offsetWidth" in docElem) { | |
467 width = docElem.offsetWidth; | |
468 } | |
469 | |
470 var end_time = Date.now(); | |
471 var time = (end_time - start_time); | |
472 | |
473 // does this page want to do its own timing? | |
474 // if so, we shouldn't be here | |
475 if (plPageFlags() & TEST_DOES_OWN_TIMING) { | |
476 dumpLine("tp: Bubbling onload handler used with page that does its own timing?"); | |
477 plStop(true); | |
478 } | |
479 | |
480 plRecordTime(time); | |
481 | |
482 if (doRenderTest) | |
483 runRenderTest(); | |
484 | |
485 plNextPage(); | |
486 } | |
487 | |
488 // the onload handler used for remote (e10s) browser | |
489 function plLoadHandlerMessage(message) { | |
490 _loadHandlerMessage(); | |
491 } | |
492 | |
493 // the mozafterpaint handler for remote (e10s) browser | |
494 function plPaintHandler(message) { | |
495 _loadHandlerMessage(); | |
496 } | |
497 | |
498 // the core handler for remote (e10s) browser | |
499 function _loadHandlerMessage() { | |
500 if (timeout > 0) { | |
501 clearTimeout(timeoutEvent); | |
502 } | |
503 | |
504 var time = -1; | |
505 | |
506 // does this page want to do its own timing? | |
507 if ((plPageFlags() & TEST_DOES_OWN_TIMING)) { | |
508 if (typeof(gStartTime) != "number") | |
509 gStartTime = Date.parse(gStartTime); | |
510 | |
511 if (gTime >= 0) { | |
512 if (useMozAfterPaint && gStartTime >= 0) { | |
513 gTime = Date.now() - gStartTime; | |
514 gStartTime = -1; | |
515 } else if (useMozAfterPaint) { | |
516 gTime = -1; | |
517 } | |
518 time = gTime; | |
519 gTime = -1; | |
520 } | |
521 | |
522 } else { | |
523 var end_time = Date.now(); | |
524 time = (end_time - start_time); | |
525 } | |
526 | |
527 if (time >= 0) { | |
528 plRecordTime(time); | |
529 if (doRenderTest) | |
530 runRenderTest(); | |
531 | |
532 plNextPage(); | |
533 } | |
534 } | |
535 | |
536 // the record time handler used for remote (e10s) browser | |
537 function plRecordTimeMessage(message) { | |
538 gTime = message.json.time; | |
539 if (useMozAfterPaint) { | |
540 gStartTime = message.json.startTime; | |
541 } | |
542 _loadHandlerMessage(); | |
543 } | |
544 | |
545 function runRenderTest() { | |
546 const redrawsPerSample = 500; | |
547 | |
548 if (!Ci.nsIDOMWindowUtils) | |
549 return; | |
550 | |
551 var win; | |
552 | |
553 if (browserWindow) | |
554 win = content.contentWindow; | |
555 else | |
556 win = window; | |
557 var wu = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); | |
558 | |
559 var start = Date.now(); | |
560 for (var j = 0; j < redrawsPerSample; j++) | |
561 wu.redraw(); | |
562 var end = Date.now(); | |
563 | |
564 renderReport.recordTime(pageIndex, end - start); | |
565 } | |
566 | |
567 function plStop(force) { | |
568 if (reportRSS) { | |
569 collectMemory(plStopAll, force); | |
570 } else { | |
571 plStopAll(force); | |
572 } | |
573 } | |
574 | |
575 function plStopAll(force) { | |
576 try { | |
577 if (force == false) { | |
578 pageIndex = 0; | |
579 if (cycle < NUM_CYCLES-1) { | |
580 cycle++; | |
581 setTimeout(plLoadPage, delay); | |
582 return; | |
583 } | |
584 | |
585 var formats = reportFormat.split(","); | |
586 | |
587 if (!renderReport) { | |
588 for each (var fmt in formats) | |
589 dumpLine(report.getReport(fmt)); | |
590 } | |
591 else { | |
592 dumpLine ("*************** Render report *******************"); | |
593 for each (var fmt in formats) | |
594 dumpLine(renderReport.getReport(fmt)); | |
595 } | |
596 } | |
597 } catch (e) { | |
598 dumpLine(e); | |
599 } | |
600 | |
601 if (reportRSS) { | |
602 stopMemCollector(); | |
603 } | |
604 | |
605 if (content) { | |
606 content.removeEventListener('load', plLoadHandlerCapturing, true); | |
607 content.removeEventListener('load', plLoadHandler, true); | |
608 if (useMozAfterPaint) | |
609 content.removeEventListener("MozAfterPaint", plPaintedCapturing, true); | |
610 content.removeEventListener("MozAfterPaint", plPainted, true); | |
611 | |
612 if (content.getAttribute("remote") == "true") { | |
613 content.messageManager.removeMessageListener('PageLoader:Load', plLoadHandlerMessage); | |
614 content.messageManager.removeMessageListener('PageLoader:RecordTime', plRecordTimeMessage); | |
615 if (useMozAfterPaint) | |
616 content.messageManager.removeMessageListener('PageLoader:MozAfterPaint', plPaintHandler); | |
617 | |
618 content.messageManager.loadFrameScript("data:,removeEventListener('load', _contentLoadHandler, true);", false); | |
619 } | |
620 } | |
621 | |
622 if (MozillaFileLogger) | |
623 MozillaFileLogger.close(); | |
624 | |
625 goQuitApplication(); | |
626 } | |
627 | |
628 /* Returns array */ | |
629 function plLoadURLsFromURI(manifestUri) { | |
630 var fstream = Cc["@mozilla.org/network/file-input-stream;1"] | |
631 .createInstance(Ci.nsIFileInputStream); | |
632 var uriFile = manifestUri.QueryInterface(Ci.nsIFileURL); | |
633 | |
634 fstream.init(uriFile.file, -1, 0, 0); | |
635 var lstream = fstream.QueryInterface(Ci.nsILineInputStream); | |
636 | |
637 var d = []; | |
638 | |
639 var lineNo = 0; | |
640 var line = {value:null}; | |
641 var more; | |
642 do { | |
643 lineNo++; | |
644 more = lstream.readLine(line); | |
645 var s = line.value; | |
646 | |
647 // strip comments | |
648 s = s.replace(/#.*/, ''); | |
649 | |
650 // strip leading and trailing whitespace | |
651 s = s.replace(/^\s*/, '').replace(/\s*$/, ''); | |
652 | |
653 if (!s) | |
654 continue; | |
655 | |
656 var flags = 0; | |
657 var urlspec = s; | |
658 | |
659 // split on whitespace, and figure out if we have any flags | |
660 var items = s.split(/\s+/); | |
661 if (items[0] == "include") { | |
662 if (items.length != 2) { | |
663 dumpLine("tp: Error on line " + lineNo + " in " + manifestUri.spec + ": include must be followed by the manifest to include!"); | |
664 return null; | |
665 } | |
666 | |
667 var subManifest = gIOS.newURI(items[1], null, manifestUri); | |
668 if (subManifest == null) { | |
669 dumpLine("tp: invalid URI on line " + manifestUri.spec + ":" + lineNo + " : '" + line.value + "'"); | |
670 return null; | |
671 } | |
672 | |
673 var subItems = plLoadURLsFromURI(subManifest); | |
674 if (subItems == null) | |
675 return null; | |
676 d = d.concat(subItems); | |
677 } else { | |
678 if (items.length == 2) { | |
679 if (items[0].indexOf("%") != -1) | |
680 flags |= TEST_DOES_OWN_TIMING; | |
681 | |
682 urlspec = items[1]; | |
683 } else if (items.length != 1) { | |
684 dumpLine("tp: Error on line " + lineNo + " in " + manifestUri.spec + ": whitespace must be %-escaped!"); | |
685 return null; | |
686 } | |
687 | |
688 var url = gIOS.newURI(urlspec, null, manifestUri); | |
689 | |
690 if (pageFilterRegexp && !pageFilterRegexp.test(url.spec)) | |
691 continue; | |
692 | |
693 d.push({ url: url, | |
694 flags: flags }); | |
695 } | |
696 } while (more); | |
697 | |
698 return d; | |
699 } | |
700 | |
701 function dumpLine(str) { | |
702 if (MozillaFileLogger) | |
703 MozillaFileLogger.log(str + "\n"); | |
704 dump(str); | |
705 dump("\n"); | |
706 } |