1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/console/content/consoleBindings.xml Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,547 @@ 1.4 +<?xml version="1.0"?> 1.5 +<!-- This Source Code Form is subject to the terms of the Mozilla Public 1.6 + - License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> 1.8 + 1.9 + 1.10 +<!DOCTYPE bindings SYSTEM "chrome://global/locale/console.dtd"> 1.11 + 1.12 +<bindings id="consoleBindings" 1.13 + xmlns="http://www.mozilla.org/xbl" 1.14 + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 1.15 + xmlns:xbl="http://www.mozilla.org/xbl"> 1.16 + 1.17 + <binding id="console-box" extends="xul:box"> 1.18 + <content> 1.19 + <xul:stringbundle src="chrome://global/locale/console.properties" role="string-bundle"/> 1.20 + <xul:vbox class="console-box-internal"> 1.21 + <xul:vbox class="console-rows" role="console-rows" xbl:inherits="dir=sortOrder"/> 1.22 + </xul:vbox> 1.23 + </content> 1.24 + 1.25 + <implementation> 1.26 + <field name="limit" readonly="true"> 1.27 + 250 1.28 + </field> 1.29 + 1.30 + <field name="fieldMaxLength" readonly="true"> 1.31 + <!-- Limit displayed string lengths to avoid performance issues. (Bug 796179 and 831020) --> 1.32 + 200 1.33 + </field> 1.34 + 1.35 + <field name="showChromeErrors" readonly="true"> 1.36 + Services.prefs.getBoolPref("javascript.options.showInConsole"); 1.37 + </field> 1.38 + 1.39 + <property name="count" readonly="true"> 1.40 + <getter>return this.mCount</getter> 1.41 + </property> 1.42 + 1.43 + <property name="mode"> 1.44 + <getter>return this.mMode;</getter> 1.45 + <setter><![CDATA[ 1.46 + if (this.mode != val) { 1.47 + this.mMode = val || "All"; 1.48 + this.setAttribute("mode", this.mMode); 1.49 + this.selectedItem = null; 1.50 + } 1.51 + return val; 1.52 + ]]></setter> 1.53 + </property> 1.54 + 1.55 + <property name="filter"> 1.56 + <getter>return this.mFilter;</getter> 1.57 + <setter><![CDATA[ 1.58 + val = val.toLowerCase(); 1.59 + if (this.mFilter != val) { 1.60 + this.mFilter = val; 1.61 + for (let aRow of this.mConsoleRowBox.children) { 1.62 + this.filterElement(aRow); 1.63 + } 1.64 + } 1.65 + return val; 1.66 + ]]></setter> 1.67 + </property> 1.68 + 1.69 + <property name="sortOrder"> 1.70 + <getter>return this.getAttribute("sortOrder");</getter> 1.71 + <setter>this.setAttribute("sortOrder", val); return val;</setter> 1.72 + </property> 1.73 + <field name="mSelectedItem">null</field> 1.74 + <property name="selectedItem"> 1.75 + <getter>return this.mSelectedItem</getter> 1.76 + <setter><![CDATA[ 1.77 + if (this.mSelectedItem) 1.78 + this.mSelectedItem.removeAttribute("selected"); 1.79 + 1.80 + this.mSelectedItem = val; 1.81 + if (val) 1.82 + val.setAttribute("selected", "true"); 1.83 + 1.84 + // Update edit commands 1.85 + window.updateCommands("focus"); 1.86 + return val; 1.87 + ]]></setter> 1.88 + </property> 1.89 + 1.90 + <method name="init"> 1.91 + <body><![CDATA[ 1.92 + this.mCount = 0; 1.93 + 1.94 + this.mConsoleListener = { 1.95 + console: this, 1.96 + observe : function(aObject) { 1.97 + // The message can arrive a little bit after the xbl binding has been 1.98 + // unbind. So node.appendItem will not be available anymore. 1.99 + if ('appendItem' in this.console) 1.100 + this.console.appendItem(aObject); 1.101 + } 1.102 + }; 1.103 + 1.104 + this.mConsoleRowBox = document.getAnonymousElementByAttribute(this, "role", "console-rows"); 1.105 + this.mStrBundle = document.getAnonymousElementByAttribute(this, "role", "string-bundle"); 1.106 + 1.107 + try { 1.108 + Services.console.registerListener(this.mConsoleListener); 1.109 + } catch (ex) { 1.110 + appendItem( 1.111 + "Unable to display errors - couldn't get Console Service component. " + 1.112 + "(Missing @mozilla.org/consoleservice;1)"); 1.113 + return; 1.114 + } 1.115 + 1.116 + this.mMode = this.getAttribute("mode") || "All"; 1.117 + this.mFilter = ""; 1.118 + 1.119 + this.appendInitialItems(); 1.120 + window.controllers.insertControllerAt(0, this._controller); 1.121 + ]]></body> 1.122 + </method> 1.123 + 1.124 + <method name="destroy"> 1.125 + <body><![CDATA[ 1.126 + Services.console.unregisterListener(this.mConsoleListener); 1.127 + window.controllers.removeController(this._controller); 1.128 + ]]></body> 1.129 + </method> 1.130 + 1.131 + <method name="appendInitialItems"> 1.132 + <body><![CDATA[ 1.133 + var messages = Services.console.getMessageArray(); 1.134 + 1.135 + // In case getMessageArray returns 0-length array as null 1.136 + if (!messages) 1.137 + messages = []; 1.138 + 1.139 + var limit = messages.length - this.limit; 1.140 + if (limit < 0) limit = 0; 1.141 + 1.142 + // Checks if console ever been cleared 1.143 + for (var i = messages.length - 1; i >= limit; --i) 1.144 + if (!messages[i].message) 1.145 + break; 1.146 + 1.147 + // Populate with messages after latest "clear" 1.148 + while (++i < messages.length) 1.149 + this.appendItem(messages[i]); 1.150 + ]]></body> 1.151 + </method> 1.152 + 1.153 + <method name="appendItem"> 1.154 + <parameter name="aObject"/> 1.155 + <body><![CDATA[ 1.156 + try { 1.157 + // Try to QI it to a script error to get more info 1.158 + var scriptError = aObject.QueryInterface(Components.interfaces.nsIScriptError); 1.159 + 1.160 + // filter chrome urls 1.161 + if (!this.showChromeErrors && scriptError.sourceName.substr(0, 9) == "chrome://") 1.162 + return; 1.163 + 1.164 + // filter private windows 1.165 + if (scriptError.isFromPrivateWindow) 1.166 + return; 1.167 + 1.168 + this.appendError(scriptError); 1.169 + } catch (ex) { 1.170 + try { 1.171 + // Try to QI it to a console message 1.172 + var msg = aObject.QueryInterface(Components.interfaces.nsIConsoleMessage); 1.173 + if (msg.message) 1.174 + this.appendMessage(msg.message); 1.175 + else // observed a null/"clear" message 1.176 + this.clearConsole(); 1.177 + } catch (ex2) { 1.178 + // Give up and append the object itself as a string 1.179 + this.appendMessage(aObject); 1.180 + } 1.181 + } 1.182 + ]]></body> 1.183 + </method> 1.184 + 1.185 + <method name="_truncateIfNecessary"> 1.186 + <parameter name="aString"/> 1.187 + <parameter name="aMiddleCharacter"/> 1.188 + <body><![CDATA[ 1.189 + if (!aString || aString.length <= this.fieldMaxLength) 1.190 + return {string: aString, column: aMiddleCharacter}; 1.191 + let halfLimit = this.fieldMaxLength / 2; 1.192 + if (!aMiddleCharacter || aMiddleCharacter < 0 || aMiddleCharacter > aString.length) 1.193 + aMiddleCharacter = halfLimit; 1.194 + 1.195 + let startPosition = 0; 1.196 + let endPosition = aString.length; 1.197 + if (aMiddleCharacter - halfLimit >= 0) 1.198 + startPosition = aMiddleCharacter - halfLimit; 1.199 + if (aMiddleCharacter + halfLimit <= aString.length) 1.200 + endPosition = aMiddleCharacter + halfLimit; 1.201 + if (endPosition - startPosition < this.fieldMaxLength) 1.202 + endPosition += this.fieldMaxLength - (endPosition - startPosition); 1.203 + let truncatedString = aString.substring(startPosition, endPosition); 1.204 + let Ci = Components.interfaces; 1.205 + let ellipsis = Services.prefs.getComplexValue("intl.ellipsis", 1.206 + Ci.nsIPrefLocalizedString).data; 1.207 + if (startPosition > 0) { 1.208 + truncatedString = ellipsis + truncatedString; 1.209 + aMiddleCharacter += ellipsis.length; 1.210 + } 1.211 + if (endPosition < aString.length) 1.212 + truncatedString = truncatedString + ellipsis; 1.213 + 1.214 + return { 1.215 + string: truncatedString, 1.216 + column: aMiddleCharacter - startPosition 1.217 + }; 1.218 + ]]></body> 1.219 + </method> 1.220 + 1.221 + <method name="appendError"> 1.222 + <parameter name="aObject"/> 1.223 + <body><![CDATA[ 1.224 + var row = this.createConsoleRow(); 1.225 + var nsIScriptError = Components.interfaces.nsIScriptError; 1.226 + 1.227 + // Is this error actually just a non-fatal warning? 1.228 + var warning = aObject.flags & nsIScriptError.warningFlag != 0; 1.229 + 1.230 + var typetext = warning ? "typeWarning" : "typeError"; 1.231 + row.setAttribute("typetext", this.mStrBundle.getString(typetext)); 1.232 + row.setAttribute("type", warning ? "warning" : "error"); 1.233 + row.setAttribute("msg", aObject.errorMessage); 1.234 + row.setAttribute("category", aObject.category); 1.235 + row.setAttribute("time", this.properFormatTime(aObject.timeStamp)); 1.236 + if (aObject.lineNumber || aObject.sourceName) { 1.237 + row.setAttribute("href", this._truncateIfNecessary(aObject.sourceName).string); 1.238 + row.mSourceName = aObject.sourceName; 1.239 + row.setAttribute("line", aObject.lineNumber); 1.240 + } else { 1.241 + row.setAttribute("hideSource", "true"); 1.242 + } 1.243 + if (aObject.sourceLine) { 1.244 + let sourceLine = aObject.sourceLine.replace(/\s/g, " "); 1.245 + let truncatedLineObj = this._truncateIfNecessary(sourceLine, aObject.columnNumber); 1.246 + row.setAttribute("code", truncatedLineObj.string); 1.247 + row.mSourceLine = sourceLine; 1.248 + if (aObject.columnNumber) { 1.249 + row.setAttribute("col", aObject.columnNumber); 1.250 + row.setAttribute("errorDots", this.repeatChar(" ", truncatedLineObj.column)); 1.251 + row.setAttribute("errorCaret", " "); 1.252 + } else { 1.253 + row.setAttribute("hideCaret", "true"); 1.254 + } 1.255 + } else { 1.256 + row.setAttribute("hideCode", "true"); 1.257 + } 1.258 + 1.259 + this.appendConsoleRow(row); 1.260 + ]]></body> 1.261 + </method> 1.262 + 1.263 + <method name="appendMessage"> 1.264 + <parameter name="aMessage"/> 1.265 + <parameter name="aType"/> 1.266 + <body><![CDATA[ 1.267 + var row = this.createConsoleRow(); 1.268 + row.setAttribute("type", aType || "message"); 1.269 + row.setAttribute("msg", aMessage); 1.270 + this.appendConsoleRow(row); 1.271 + ]]></body> 1.272 + </method> 1.273 + 1.274 + <method name="clear"> 1.275 + <body><![CDATA[ 1.276 + // add a "clear" message (mainly for other listeners) 1.277 + Services.console.logStringMessage(null); 1.278 + Services.console.reset(); 1.279 + ]]></body> 1.280 + </method> 1.281 + 1.282 + <method name="properFormatTime"> 1.283 + <parameter name="aTime"/> 1.284 + <body><![CDATA[ 1.285 + const dateServ = Components.classes["@mozilla.org/intl/scriptabledateformat;1"] 1.286 + .getService(Components.interfaces.nsIScriptableDateFormat); 1.287 + let errorTime = new Date(aTime); 1.288 + return dateServ.FormatDateTime("", dateServ.dateFormatShort, dateServ.timeFormatSeconds, 1.289 + errorTime.getFullYear(), errorTime.getMonth() + 1, errorTime.getDate(), 1.290 + errorTime.getHours(), errorTime.getMinutes(), errorTime.getSeconds()); 1.291 + ]]></body> 1.292 + </method> 1.293 + 1.294 + <method name="copySelectedItem"> 1.295 + <body><![CDATA[ 1.296 + if (this.mSelectedItem) try { 1.297 + const clipURI = "@mozilla.org/widget/clipboardhelper;1"; 1.298 + const clipI = Components.interfaces.nsIClipboardHelper; 1.299 + var clipboard = Components.classes[clipURI].getService(clipI); 1.300 + 1.301 + clipboard.copyString(this.mSelectedItem.toString(), document); 1.302 + } catch (ex) { 1.303 + // Unable to copy anything, die quietly 1.304 + } 1.305 + ]]></body> 1.306 + </method> 1.307 + 1.308 + <method name="createConsoleRow"> 1.309 + <body><![CDATA[ 1.310 + var row = document.createElement("box"); 1.311 + row.setAttribute("class", "console-row"); 1.312 + row._IsConsoleRow = true; 1.313 + row._ConsoleBox = this; 1.314 + return row; 1.315 + ]]></body> 1.316 + </method> 1.317 + 1.318 + <method name="appendConsoleRow"> 1.319 + <parameter name="aRow"/> 1.320 + <body><![CDATA[ 1.321 + this.filterElement(aRow); 1.322 + this.mConsoleRowBox.appendChild(aRow); 1.323 + if (++this.mCount > this.limit) this.deleteFirst(); 1.324 + ]]></body> 1.325 + </method> 1.326 + 1.327 + <method name="deleteFirst"> 1.328 + <body><![CDATA[ 1.329 + var node = this.mConsoleRowBox.firstChild; 1.330 + this.mConsoleRowBox.removeChild(node); 1.331 + --this.mCount; 1.332 + ]]></body> 1.333 + </method> 1.334 + 1.335 + <method name="clearConsole"> 1.336 + <body><![CDATA[ 1.337 + if (this.mCount == 0) // already clear 1.338 + return; 1.339 + this.mCount = 0; 1.340 + 1.341 + var newRows = this.mConsoleRowBox.cloneNode(false); 1.342 + this.mConsoleRowBox.parentNode.replaceChild(newRows, this.mConsoleRowBox); 1.343 + this.mConsoleRowBox = newRows; 1.344 + this.selectedItem = null; 1.345 + ]]></body> 1.346 + </method> 1.347 + 1.348 + <method name="filterElement"> 1.349 + <parameter name="aRow" /> 1.350 + <body><![CDATA[ 1.351 + let anyMatch = ["msg", "line", "code"].some(function (key) { 1.352 + return (aRow.hasAttribute(key) && 1.353 + this.stringMatchesFilters(aRow.getAttribute(key), this.mFilter)); 1.354 + }, this) || (aRow.mSourceName && 1.355 + this.stringMatchesFilters(aRow.mSourceName, this.mFilter)); 1.356 + 1.357 + if (anyMatch) { 1.358 + aRow.classList.remove("filtered-by-string") 1.359 + } else { 1.360 + aRow.classList.add("filtered-by-string") 1.361 + } 1.362 + ]]></body> 1.363 + </method> 1.364 + 1.365 + <!-- UTILITY FUNCTIONS --> 1.366 + 1.367 + <method name="repeatChar"> 1.368 + <parameter name="aChar"/> 1.369 + <parameter name="aCol"/> 1.370 + <body><![CDATA[ 1.371 + if (--aCol <= 0) 1.372 + return ""; 1.373 + 1.374 + for (var i = 2; i < aCol; i += i) 1.375 + aChar += aChar; 1.376 + 1.377 + return aChar + aChar.slice(0, aCol - aChar.length); 1.378 + ]]></body> 1.379 + </method> 1.380 + 1.381 + <method name="stringMatchesFilters"> 1.382 + <parameter name="aString"/> 1.383 + <parameter name="aFilter"/> 1.384 + <body><![CDATA[ 1.385 + if (!aString || !aFilter) { 1.386 + return true; 1.387 + } 1.388 + 1.389 + let searchStr = aString.toLowerCase(); 1.390 + let filterStrings = aFilter.split(/\s+/); 1.391 + return !filterStrings.some(function (f) { 1.392 + return searchStr.indexOf(f) == -1; 1.393 + }); 1.394 + ]]></body> 1.395 + </method> 1.396 + 1.397 + <constructor> this.init(); </constructor> 1.398 + <destructor> this.destroy(); </destructor> 1.399 + 1.400 + <!-- Command controller for the copy command --> 1.401 + <field name="_controller"><![CDATA[({ 1.402 + _outer: this, 1.403 + 1.404 + QueryInterface: function(aIID) { 1.405 + if (aIID.equals(Components.interfaces.nsIController) || 1.406 + aIID.equals(Components.interfaces.nsISupports)) 1.407 + return this; 1.408 + throw Components.results.NS_NOINTERFACE; 1.409 + }, 1.410 + 1.411 + supportsCommand: function(aCommand) { 1.412 + return aCommand == "cmd_copy"; 1.413 + }, 1.414 + 1.415 + isCommandEnabled: function(aCommand) { 1.416 + return aCommand == "cmd_copy" && this._outer.selectedItem; 1.417 + }, 1.418 + 1.419 + doCommand: function(aCommand) { 1.420 + if (aCommand == "cmd_copy") 1.421 + this._outer.copySelectedItem(); 1.422 + }, 1.423 + 1.424 + onEvent: function() { } 1.425 + });]]></field> 1.426 + </implementation> 1.427 + 1.428 + <handlers> 1.429 + <handler event="mousedown"><![CDATA[ 1.430 + if (event.button == 0 || event.button == 2) { 1.431 + var target = event.originalTarget; 1.432 + 1.433 + while (target && !("_IsConsoleRow" in target)) 1.434 + target = target.parentNode; 1.435 + 1.436 + if (target) 1.437 + this.selectedItem = target; 1.438 + } 1.439 + ]]></handler> 1.440 + </handlers> 1.441 + </binding> 1.442 + 1.443 + <binding id="error" extends="xul:box"> 1.444 + <content> 1.445 + <xul:box class="console-row-internal-box" flex="1"> 1.446 + <xul:box class="console-row-icon" align="center" xbl:inherits="selected"> 1.447 + <xul:image class="console-icon" xbl:inherits="src,type"/> 1.448 + </xul:box> 1.449 + <xul:vbox class="console-row-content" xbl:inherits="selected" flex="1"> 1.450 + <xul:box class="console-row-msg" align="start"> 1.451 + <xul:label class="label" xbl:inherits="value=typetext"/> 1.452 + <xul:description class="console-error-msg" xbl:inherits="xbl:text=msg" flex="1"/> 1.453 + <xul:label class="label console-time" xbl:inherits="value=time"/> 1.454 + </xul:box> 1.455 + <xul:box class="console-row-file" xbl:inherits="hidden=hideSource"> 1.456 + <xul:label class="label" value="&errFile.label;"/> 1.457 + <xul:box class="console-error-source" xbl:inherits="href,line"/> 1.458 + <xul:spacer flex="1"/> 1.459 + <xul:hbox class="lineNumberRow" xbl:inherits="line"> 1.460 + <xul:label class="label" value="&errLine.label;"/> 1.461 + <xul:label class="label" xbl:inherits="value=line"/> 1.462 + </xul:hbox> 1.463 + </xul:box> 1.464 + <xul:vbox class="console-row-code" xbl:inherits="selected,hidden=hideCode"> 1.465 + <xul:label class="monospace console-code" xbl:inherits="value=code" crop="end"/> 1.466 + <xul:box xbl:inherits="hidden=hideCaret"> 1.467 + <xul:label class="monospace console-dots" xbl:inherits="value=errorDots"/> 1.468 + <xul:label class="monospace console-caret" xbl:inherits="value=errorCaret"/> 1.469 + <xul:spacer flex="1"/> 1.470 + </xul:box> 1.471 + </xul:vbox> 1.472 + </xul:vbox> 1.473 + </xul:box> 1.474 + </content> 1.475 + 1.476 + <implementation> 1.477 + <field name="mSourceName">null</field> 1.478 + <field name="mSourceLine">null</field> 1.479 + 1.480 + <method name="toString"> 1.481 + <body><![CDATA[ 1.482 + let msg = ""; 1.483 + let strBundle = this._ConsoleBox.mStrBundle; 1.484 + 1.485 + if (this.hasAttribute("time")) 1.486 + msg += strBundle.getFormattedString("errTime", [this.getAttribute("time")]) + "\n"; 1.487 + 1.488 + msg += this.getAttribute("typetext") + " " + this.getAttribute("msg"); 1.489 + 1.490 + if (this.hasAttribute("line") && this.mSourceName) { 1.491 + msg += "\n" + strBundle.getFormattedString("errFile", 1.492 + [this.mSourceName]) + "\n"; 1.493 + if (this.hasAttribute("col")) { 1.494 + msg += strBundle.getFormattedString("errLineCol", 1.495 + [this.getAttribute("line"), this.getAttribute("col")]); 1.496 + } else 1.497 + msg += strBundle.getFormattedString("errLine", [this.getAttribute("line")]); 1.498 + } 1.499 + 1.500 + if (this.hasAttribute("code")) 1.501 + msg += "\n" + strBundle.getString("errCode") + "\n" + this.mSourceLine; 1.502 + 1.503 + return msg; 1.504 + ]]></body> 1.505 + </method> 1.506 + </implementation> 1.507 + 1.508 + </binding> 1.509 + 1.510 + <binding id="message" extends="xul:box"> 1.511 + <content> 1.512 + <xul:box class="console-internal-box" flex="1"> 1.513 + <xul:box class="console-row-icon" align="center"> 1.514 + <xul:image class="console-icon" xbl:inherits="src,type"/> 1.515 + </xul:box> 1.516 + <xul:vbox class="console-row-content" xbl:inherits="selected" flex="1"> 1.517 + <xul:vbox class="console-row-msg" flex="1"> 1.518 + <xul:description class="console-msg-text" xbl:inherits="xbl:text=msg"/> 1.519 + </xul:vbox> 1.520 + </xul:vbox> 1.521 + </xul:box> 1.522 + </content> 1.523 + 1.524 + <implementation> 1.525 + <method name="toString"> 1.526 + <body><![CDATA[ 1.527 + return this.getAttribute("msg"); 1.528 + ]]></body> 1.529 + </method> 1.530 + </implementation> 1.531 + </binding> 1.532 + 1.533 + <binding id="console-error-source" extends="xul:box"> 1.534 + <content> 1.535 + <xul:label class="text-link" xbl:inherits="value=href" crop="right"/> 1.536 + </content> 1.537 + 1.538 + <handlers> 1.539 + <handler event="click" phase="capturing" button="0" preventdefault="true"> 1.540 + <![CDATA[ 1.541 + var url = document.getBindingParent(this).mSourceName; 1.542 + url = url.substring(url.lastIndexOf(" ") + 1); 1.543 + var line = getAttribute("line"); 1.544 + gViewSourceUtils.viewSource(url, null, null, line); 1.545 + ]]> 1.546 + </handler> 1.547 + </handlers> 1.548 + </binding> 1.549 + 1.550 +</bindings>