summaryrefslogtreecommitdiffstats
path: root/toolkit/components/aboutcheckerboard
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/aboutcheckerboard')
-rw-r--r--toolkit/components/aboutcheckerboard/content/aboutCheckerboard.css49
-rw-r--r--toolkit/components/aboutcheckerboard/content/aboutCheckerboard.js276
-rw-r--r--toolkit/components/aboutcheckerboard/content/aboutCheckerboard.xhtml55
-rw-r--r--toolkit/components/aboutcheckerboard/jar.mn8
-rw-r--r--toolkit/components/aboutcheckerboard/moz.build10
5 files changed, 398 insertions, 0 deletions
diff --git a/toolkit/components/aboutcheckerboard/content/aboutCheckerboard.css b/toolkit/components/aboutcheckerboard/content/aboutCheckerboard.css
new file mode 100644
index 000000000..7f88612db
--- /dev/null
+++ b/toolkit/components/aboutcheckerboard/content/aboutCheckerboard.css
@@ -0,0 +1,49 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+table.listing {
+ width: 100%;
+}
+
+table th, table td {
+ padding: 5px;
+ border: inset 2px black;
+ margin: 0px;
+ width: 50%;
+ vertical-align: top;
+}
+
+hr {
+ clear: both;
+ margin: 10px;
+}
+
+iframe {
+ width: 100%;
+ height: 900px;
+}
+
+#player, #raw {
+ width: 800px;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+#controls {
+ text-align: center;
+}
+
+#canvas {
+ border: solid 1px black;
+}
+
+#active {
+ width: 100%;
+ border: solid 1px black;
+ margin-top: 0;
+}
+
+#trace {
+ width: 100%;
+}
diff --git a/toolkit/components/aboutcheckerboard/content/aboutCheckerboard.js b/toolkit/components/aboutcheckerboard/content/aboutCheckerboard.js
new file mode 100644
index 000000000..c64a80a05
--- /dev/null
+++ b/toolkit/components/aboutcheckerboard/content/aboutCheckerboard.js
@@ -0,0 +1,276 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+var trace;
+var service;
+var reports;
+
+function onLoad() {
+ trace = document.getElementById('trace');
+ service = new CheckerboardReportService();
+ updateEnabled();
+ reports = service.getReports();
+ for (var i = 0; i < reports.length; i++) {
+ let text = "Severity " + reports[i].severity + " at " + new Date(reports[i].timestamp).toString();
+ let link = document.createElement('a');
+ link.href = 'javascript:showReport(' + i + ')';
+ link.textContent = text;
+ let bullet = document.createElement('li');
+ bullet.appendChild(link);
+ document.getElementById(reports[i].reason).appendChild(bullet);
+ }
+}
+
+function updateEnabled() {
+ let enabled = document.getElementById('enabled');
+ if (service.isRecordingEnabled()) {
+ enabled.textContent = 'enabled';
+ enabled.style.color = 'green';
+ } else {
+ enabled.textContent = 'disabled';
+ enabled.style.color = 'red';
+ }
+}
+
+function toggleEnabled() {
+ service.setRecordingEnabled(!service.isRecordingEnabled());
+ updateEnabled();
+}
+
+function flushReports() {
+ service.flushActiveReports();
+}
+
+function showReport(index) {
+ trace.value = reports[index].log;
+ loadData();
+}
+
+// -- Code to load and render the trace --
+
+const CANVAS_USE_RATIO = 0.75;
+const FRAME_INTERVAL_MS = 50;
+const VECTOR_NORMALIZED_MAGNITUDE = 30.0;
+
+var renderData = new Array();
+var currentFrame = 0;
+var playing = false;
+var timerId = 0;
+
+var minX = undefined;
+var minY = undefined;
+var maxX = undefined;
+var maxY = undefined;
+
+function log(x) {
+ if (console) {
+ console.log(x);
+ }
+}
+
+function getFlag(flag) {
+ return document.getElementById(flag).checked;
+}
+
+// parses the lines in the textarea, ignoring anything that doesn't have RENDERTRACE.
+// for each matching line, tokenizes on whitespace and ignores all tokens prior to
+// RENDERTRACE. Additional info can be included at the end of the line, and will be
+// displayed but not parsed. Allowed syntaxes:
+// <junk> RENDERTRACE <timestamp> rect <color> <x> <y> <width> <height> [extraInfo]
+function loadData() {
+ stopPlay();
+ renderData = new Array();
+ currentFrame = 0;
+ minX = undefined;
+ minY = undefined;
+ maxX = undefined;
+ maxY = undefined;
+
+ var charPos = 0;
+ var lastLineLength = 0;
+ var lines = trace.value.split(/\r|\n/);
+ for (var i = 0; i < lines.length; i++) {
+ charPos += lastLineLength;
+ lastLineLength = lines[i].length + 1;
+ // skip lines without RENDERTRACE
+ if (! /RENDERTRACE/.test(lines[i])) {
+ continue;
+ }
+
+ var tokens = lines[i].split(/\s+/);
+ var j = 0;
+ // skip tokens until RENDERTRACE
+ while (j < tokens.length && tokens[j++] != "RENDERTRACE"); // empty loop body
+ if (j >= tokens.length - 2) {
+ log("Error parsing line: " + lines[i]);
+ continue;
+ }
+
+ var timestamp = tokens[j++];
+ var destIndex = renderData.length;
+ if (destIndex == 0) {
+ // create the initial frame
+ renderData.push({
+ timestamp: timestamp,
+ rects: {},
+ });
+ } else if (renderData[destIndex - 1].timestamp == timestamp) {
+ // timestamp hasn't changed use, so update the previous object
+ destIndex--;
+ } else {
+ // clone a new copy of the last frame and update timestamp
+ renderData.push(JSON.parse(JSON.stringify(renderData[destIndex - 1])));
+ renderData[destIndex].timestamp = timestamp;
+ }
+
+ switch (tokens[j++]) {
+ case "rect":
+ if (j > tokens.length - 5) {
+ log("Error parsing line: " + lines[i]);
+ continue;
+ }
+
+ var rect = {};
+ var color = tokens[j++];
+ renderData[destIndex].rects[color] = rect;
+ rect.x = parseFloat(tokens[j++]);
+ rect.y = parseFloat(tokens[j++]);
+ rect.width = parseFloat(tokens[j++]);
+ rect.height = parseFloat(tokens[j++]);
+ rect.dataText = trace.value.substring(charPos, charPos + lines[i].length);
+
+ if (!getFlag('excludePageFromZoom') || color != 'brown') {
+ if (typeof minX == "undefined") {
+ minX = rect.x;
+ minY = rect.y;
+ maxX = rect.x + rect.width;
+ maxY = rect.y + rect.height;
+ } else {
+ minX = Math.min(minX, rect.x);
+ minY = Math.min(minY, rect.y);
+ maxX = Math.max(maxX, rect.x + rect.width);
+ maxY = Math.max(maxY, rect.y + rect.height);
+ }
+ }
+ break;
+
+ default:
+ log("Error parsing line " + lines[i]);
+ break;
+ }
+ }
+
+ if (! renderFrame()) {
+ alert("No data found; nothing to render!");
+ }
+}
+
+// render the current frame (i.e. renderData[currentFrame])
+// returns false if currentFrame is out of bounds, true otherwise
+function renderFrame() {
+ var frame = currentFrame;
+ if (frame < 0 || frame >= renderData.length) {
+ log("Invalid frame index");
+ return false;
+ }
+
+ var canvas = document.getElementById('canvas');
+ if (! canvas.getContext) {
+ log("No canvas context");
+ }
+
+ var context = canvas.getContext('2d');
+
+ // midpoint of the bounding box
+ var midX = (minX + maxX) / 2.0;
+ var midY = (minY + maxY) / 2.0;
+
+ // midpoint of the canvas
+ var cmx = canvas.width / 2.0;
+ var cmy = canvas.height / 2.0;
+
+ // scale factor
+ var scale = CANVAS_USE_RATIO * Math.min(canvas.width / (maxX - minX), canvas.height / (maxY - minY));
+
+ function projectX(value) {
+ return cmx + ((value - midX) * scale);
+ }
+
+ function projectY(value) {
+ return cmy + ((value - midY) * scale);
+ }
+
+ function drawRect(color, rect) {
+ context.strokeStyle = color;
+ context.strokeRect(
+ projectX(rect.x),
+ projectY(rect.y),
+ rect.width * scale,
+ rect.height * scale);
+ }
+
+ // clear canvas
+ context.fillStyle = 'white';
+ context.fillRect(0, 0, canvas.width, canvas.height);
+ var activeData = '';
+ // draw rects
+ for (var i in renderData[frame].rects) {
+ drawRect(i, renderData[frame].rects[i]);
+ activeData += "\n" + renderData[frame].rects[i].dataText;
+ }
+ // draw timestamp and frame counter
+ context.fillStyle = 'black';
+ context.fillText((frame + 1) + "/" + renderData.length + ": " + renderData[frame].timestamp, 5, 15);
+
+ document.getElementById('active').textContent = activeData;
+
+ return true;
+}
+
+// -- Player controls --
+
+function reset(beginning) {
+ currentFrame = (beginning ? 0 : renderData.length - 1);
+ renderFrame();
+}
+
+function step(backwards) {
+ if (playing) {
+ togglePlay();
+ }
+ currentFrame += (backwards ? -1 : 1);
+ if (! renderFrame()) {
+ currentFrame -= (backwards ? -1 : 1);
+ }
+}
+
+function pause() {
+ clearInterval(timerId);
+ playing = false;
+}
+
+function togglePlay() {
+ if (playing) {
+ pause();
+ } else {
+ timerId = setInterval(function() {
+ currentFrame++;
+ if (! renderFrame()) {
+ currentFrame--;
+ togglePlay();
+ }
+ }, FRAME_INTERVAL_MS);
+ playing = true;
+ }
+}
+
+function stopPlay() {
+ if (playing) {
+ togglePlay();
+ }
+ currentFrame = 0;
+ renderFrame();
+}
diff --git a/toolkit/components/aboutcheckerboard/content/aboutCheckerboard.xhtml b/toolkit/components/aboutcheckerboard/content/aboutCheckerboard.xhtml
new file mode 100644
index 000000000..6a8a61896
--- /dev/null
+++ b/toolkit/components/aboutcheckerboard/content/aboutCheckerboard.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta name="viewport" content="width=device-width"/>
+ <link rel="stylesheet" href="chrome://global/content/aboutCheckerboard.css" type="text/css"/>
+ <script type="text/javascript;version=1.8" src="chrome://global/content/aboutCheckerboard.js"></script>
+ </head>
+
+ <body onload="onLoad()">
+ <p>Checkerboard recording is <span id="enabled" style="color: red">undetermined</span>.
+ <button onclick="toggleEnabled()">Toggle it!</button>.</p>
+ <p>If there are active reports in progress, you can stop and flush them by clicking here:
+ <button onclick="flushReports()">Flush active reports</button></p>
+ <table class="listing" cellspacing="0">
+ <tr>
+ <th>Most severe checkerboarding reports</th>
+ <th>Most recent checkerboarding reports</th>
+ </tr>
+ <tr>
+ <td><ul id="severe"></ul></td>
+ <td><ul id="recent"></ul></td>
+ </tr>
+ </table>
+
+ <hr/>
+
+ <div id="player">
+ <div id="controls">
+ <button onclick="reset(true)">&#171;</button><!-- rewind button -->
+ <button onclick="step(true)">&lt;</button><!-- step back button -->
+ <button onclick="togglePlay()">|| &#9654;</button><!-- pause button -->
+ <button onclick="stopPlay()">&#9744;</button><!-- stop button -->
+ <button onclick="step(false)">&gt;</button><!-- step forward button -->
+ <button onclick="reset(false)">&#187;</button><!-- forward button -->
+ </div>
+ <canvas id="canvas" width="800" height="600">Canvas not supported!</canvas>
+ <pre id="active">(Details for currently visible replay frame)</pre>
+ </div>
+
+ <hr/>
+
+ <div id="raw">
+ Raw log:<br/>
+ <textarea id="trace" rows="10"></textarea>
+ <div>
+ <input type="checkbox" id="excludePageFromZoom" onclick="loadData()"/><label for="excludePageFromZoom">Exclude page coordinates from zoom calculations</label><br/>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/toolkit/components/aboutcheckerboard/jar.mn b/toolkit/components/aboutcheckerboard/jar.mn
new file mode 100644
index 000000000..64d5bfc8e
--- /dev/null
+++ b/toolkit/components/aboutcheckerboard/jar.mn
@@ -0,0 +1,8 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+toolkit.jar:
+ content/global/aboutCheckerboard.js (content/aboutCheckerboard.js)
+ content/global/aboutCheckerboard.xhtml (content/aboutCheckerboard.xhtml)
+ content/global/aboutCheckerboard.css (content/aboutCheckerboard.css)
diff --git a/toolkit/components/aboutcheckerboard/moz.build b/toolkit/components/aboutcheckerboard/moz.build
new file mode 100644
index 000000000..91d6e9662
--- /dev/null
+++ b/toolkit/components/aboutcheckerboard/moz.build
@@ -0,0 +1,10 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+JAR_MANIFESTS += ['jar.mn']
+
+with Files('**'):
+ BUG_COMPONENT = ('Core', 'Panning and Zooming')