browser/metro/base/content/console.js

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 // -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 let ConsolePanelView = {
     7   _list: null,
     8   _inited: false,
     9   _evalTextbox: null,
    10   _evalFrame: null,
    11   _evalCode: "",
    12   _bundle: null,
    13   _showChromeErrors: -1,
    14   _enabledPref: "devtools.errorconsole.enabled",
    16   get enabled() {
    17     return Services.prefs.getBoolPref(this._enabledPref);
    18   },
    20   get follow() {
    21     return document.getElementById("console-follow-checkbox").checked;
    22   },
    24   init: function cv_init() {
    25     if (this._list)
    26       return;
    28     this._list = document.getElementById("console-box");
    29     this._evalTextbox = document.getElementById("console-eval-textbox");
    30     this._bundle = Strings.browser;
    32     this._count = 0;
    33     this.limit = 250;
    34     this.fieldMaxLength = 140;
    36     try {
    37       // update users using the legacy pref
    38       if (Services.prefs.getBoolPref("browser.console.showInPanel")) {
    39         Services.prefs.setBoolPref(this._enabledPref, true);
    40         Services.prefs.clearUserPref("browser.console.showInPanel");
    41       }
    42     } catch(ex) {
    43       // likely don't have an old pref
    44     }
    45     Services.prefs.addObserver(this._enabledPref, this, false);
    46   },
    48   show: function show() {
    49     if (this._inited)
    50       return;
    51     this._inited = true;
    53     this.init(); // In case the panel is selected before init has been called.
    55     Services.console.registerListener(this);
    57     this.appendInitialItems();
    59     // Delay creation of the iframe for startup performance
    60     this._evalFrame = document.createElement("iframe");
    61     this._evalFrame.id = "console-evaluator";
    62     this._evalFrame.collapsed = true;
    63     document.getElementById("console-container").appendChild(this._evalFrame);
    65     this._evalFrame.addEventListener("load", this.loadOrDisplayResult.bind(this), true);
    66   },
    68   uninit: function cv_uninit() {
    69     if (this._inited)
    70       Services.console.unregisterListener(this);
    72     Services.prefs.removeObserver(this._enabledPref, this, false);
    73   },
    75   observe: function(aSubject, aTopic, aData) {
    76     if (aTopic == "nsPref:changed") {
    77       // We may choose to create a new menu in v2
    78       }
    79     else
    80       this.appendItem(aSubject);
    81   },
    83   showChromeErrors: function() {
    84     if (this._showChromeErrors != -1)
    85       return this._showChromeErrors;
    87     try {
    88       let pref = Services.prefs;
    89       return this._showChromeErrors = pref.getBoolPref("javascript.options.showInConsole");
    90     }
    91     catch(ex) {
    92       return this._showChromeErrors = false;
    93     }
    94   },
    96   appendItem: function cv_appendItem(aObject) {
    97     let index = -1;
    98     try {
    99       // Try to QI it to a script error to get more info
   100       let scriptError = aObject.QueryInterface(Ci.nsIScriptError);
   102       // filter chrome urls
   103       if (!this.showChromeErrors && scriptError.sourceName.substr(0, 9) == "chrome://")
   104         return;
   105       index = this.appendError(scriptError);
   106     }
   107     catch (ex) {
   108       try {
   109         // Try to QI it to a console message
   110         let msg = aObject.QueryInterface(Ci.nsIConsoleMessage);
   112         if (msg.message)
   113           index = this.appendMessage(msg.message);
   114         else // observed a null/"clear" message
   115           this.clearConsole();
   116       }
   117       catch (ex2) {
   118         // Give up and append the object itself as a string
   119         index = this.appendMessage(aObject);
   120       }
   121     }
   122     if (this.follow) {
   123       this._list.ensureIndexIsVisible(index);
   124     }
   125   },
   127   truncateIfNecessary: function (aString) {
   128     if (!aString || aString.length <= this.fieldMaxLength) {
   129       return aString;
   130     }
   131     let truncatedString = aString.substring(0, this.fieldMaxLength);
   132     let Ci = Components.interfaces;
   133     let ellipsis = Services.prefs.getComplexValue("intl.ellipsis",
   134                                                   Ci.nsIPrefLocalizedString).data;
   135     truncatedString = truncatedString + ellipsis;
   136     return truncatedString;
   137   },
   139   appendError: function cv_appendError(aObject) {
   140     let row = this.createConsoleRow();
   141     let nsIScriptError = Ci.nsIScriptError;
   143     // Is this error actually just a non-fatal warning?
   144     let warning = aObject.flags & nsIScriptError.warningFlag != 0;
   146     let typetext = warning ? "typeWarning" : "typeError";
   147     row.setAttribute("typetext", this._bundle.GetStringFromName(typetext));
   148     row.setAttribute("type", warning ? "warning" : "error");
   149     row.setAttribute("msg", aObject.errorMessage);
   150     row.setAttribute("category", aObject.category);
   151     if (aObject.lineNumber || aObject.sourceName) {
   152       row.setAttribute("href", aObject.sourceName);
   153       row.setAttribute("line", aObject.lineNumber);
   154     }
   155     else {
   156       row.setAttribute("hideSource", "true");
   157     }
   158     // hide code by default, otherwise initial item display will
   159     // hang the browser.
   160     row.setAttribute("hideCode", "true");
   161     row.setAttribute("hideCaret", "true");
   163     if (aObject.sourceLine) {
   164       row.setAttribute("code", this.truncateIfNecessary(aObject.sourceLine.replace(/\s/g, " ")));
   165       if (aObject.columnNumber) {
   166         row.setAttribute("col", aObject.columnNumber);
   167       }
   168     }
   170     let mode = document.getElementById("console-filter").value;
   171     if (mode != "all" && mode != row.getAttribute("type")) {
   172       row.collapsed = true;
   173     }
   175     row.setAttribute("onclick", "ConsolePanelView.onRowClick(this)");
   176     this.appendConsoleRow(row);
   177     return this._list.getIndexOfItem(row);
   178   },
   180   appendMessage: function cv_appendMessage (aMessage) {
   181     let row = this.createConsoleRow();
   182     row.setAttribute("type", "message");
   183     row.setAttribute("msg", aMessage);
   185     let mode = document.getElementById("console-filter").value;
   186     if (mode != "all" && mode != "message")
   187       row.collapsed = true;
   189     this.appendConsoleRow(row);
   190     return this._list.getIndexOfItem(row);
   191   },
   193   createConsoleRow: function cv_createConsoleRow() {
   194     let row = document.createElement("richlistitem");
   195     row.setAttribute("class", "console-row");
   196     return row;
   197   },
   199   appendConsoleRow: function cv_appendConsoleRow(aRow) {
   200     this._list.appendChild(aRow);
   201     if (++this._count > this.limit) {
   202       this.deleteFirst();
   203     }
   204   },
   206   deleteFirst: function cv_deleteFirst() {
   207     let node = this._list.firstChild;
   208     this._list.removeChild(node);
   209     --this._count;
   210   },
   212   appendInitialItems: function cv_appendInitialItems() {
   213     this._list.collapsed = true;
   214     let messages = Services.console.getMessageArray();
   216     // In case getMessageArray returns 0-length array as null
   217     if (!messages)
   218       messages = [];
   220     let limit = messages.length - this.limit;
   221     if (limit < 0)
   222       limit = 0;
   224     // Checks if console ever been cleared
   225     for (var i = messages.length - 1; i >= limit; --i) {
   226       if (!messages[i].message) {
   227         break;
   228       }
   229     }
   231     // Populate with messages after latest "clear"
   232     while (++i < messages.length) {
   233       this.appendItem(messages[i]);
   234     }
   235     this._list.collapsed = false;
   236   },
   238   clearConsole: function cv_clearConsole() {
   239     if (this._count == 0) // already clear
   240       return;
   241     this._count = 0;
   243     let newRows = this._list.cloneNode(false);
   244     this._list.parentNode.replaceChild(newRows, this._list);
   245     this._list = newRows;
   246     this.selectedItem = null;
   247   },
   249   copyAll: function () {
   250     let mode = document.getElementById("console-filter").value;
   251     let rows = this._list.childNodes;
   252     let copyText = "";
   253     for (let i=0; i < rows.length; i++) {
   254       let row = rows[i];
   255       if (mode == "all" || row.getAttribute ("type") == mode) {
   256         let text = "* " + row.getAttribute("msg");
   257         if (row.hasAttribute("href")) {
   258           text += "\r\n " + row.getAttribute("href") + " line:" + row.getAttribute("line");
   259         }
   260         if (row.hasAttribute("code")) {
   261           text += "\r\n " + row.getAttribute("code") + " col:" + row.getAttribute("col");
   262         }
   263         copyText += text + "\r\n";
   264       }
   265     }
   266     let clip = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
   267     clip.copyString(copyText, document);
   268   },
   270   changeMode: function cv_changeMode() {
   271     let mode = document.getElementById("console-filter").value;
   272     if (this._list.getAttribute("mode") != mode) {
   273       let rows = this._list.childNodes;
   274       for (let i=0; i < rows.length; i++) {
   275         let row = rows[i];
   276         if (mode == "all" || row.getAttribute ("type") == mode)
   277           row.collapsed = false;
   278         else
   279           row.collapsed = true;
   280       }
   281       this._list.mode = mode;
   282       this._list.scrollToIndex(0);
   283     }
   284   },
   286   onContextMenu: function cv_onContextMenu(aEvent) {
   287     let row = aEvent.target;
   288     let text = ["msg", "href", "line", "code", "col"].map(function(attr) row.getAttribute(attr))
   289                .filter(function(x) x).join("\r\n");
   291     ContextMenuUI.showContextMenu({
   292       target: row,
   293       json: {
   294         types: ["copy"],
   295         string: text,
   296         xPos: aEvent.clientX,
   297         yPos: aEvent.clientY
   298       }
   299     });
   300   },
   302   onRowClick: function (aRow) {
   303     if (aRow.hasAttribute("code")) {
   304       aRow.setAttribute("hideCode", "false");
   305     }
   306     if (aRow.hasAttribute("col")) {
   307       aRow.setAttribute("hideCaret", "false");
   308     }
   309   },
   311   onEvalKeyPress: function cv_onEvalKeyPress(aEvent) {
   312     if (aEvent.keyCode == 13)
   313       this.evaluateTypein();
   314   },
   316   onConsoleBoxKeyPress: function cv_onConsoleBoxKeyPress(aEvent) {
   317     if ((aEvent.charCode == 99 || aEvent.charCode == 67) && aEvent.ctrlKey && this._list && this._list.selectedItem) {
   318       let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
   319       clipboard.copyString(this._list.selectedItem.getAttribute("msg"), document);
   320     }
   321   },
   323   evaluateTypein: function cv_evaluateTypein() {
   324     this._evalCode = this._evalTextbox.value;
   325     this.loadOrDisplayResult();
   326   },
   328   loadOrDisplayResult: function cv_loadOrDisplayResult() {
   329     if (this._evalCode) {
   330       this._evalFrame.contentWindow.location = "javascript: " + this._evalCode.replace(/%/g, "%25");
   331       this._evalCode = "";
   332       return;
   333     }
   335     let resultRange = this._evalFrame.contentDocument.createRange();
   336     resultRange.selectNode(this._evalFrame.contentDocument.documentElement);
   337     let result = resultRange.toString();
   338     if (result)
   339       Services.console.logStringMessage(result);
   340       // or could use appendMessage which doesn't persist
   341   },
   343   repeatChar: function cv_repeatChar(aChar, aCol) {
   344     if (--aCol <= 0)
   345       return "";
   347     for (let i = 2; i < aCol; i += i)
   348       aChar += aChar;
   350     return aChar + aChar.slice(0, aCol - aChar.length);
   351   }
   352 };

mercurial