Bug 955641 - Open debug logs in a tab. r=aleth
This commit is contained in:
Родитель
8e0feeb092
Коммит
0df6181e05
|
@ -256,6 +256,11 @@ var gAccountManager = {
|
|||
Cc["@mozilla.org/widget/clipboardhelper;1"]
|
||||
.getService(Ci.nsIClipboardHelper).copyString(text);
|
||||
},
|
||||
showDebugLog: function am_showDebugLog() {
|
||||
if (!"Core" in window)
|
||||
Cu.import("resource:///modules/ibCore.jsm");
|
||||
Core.showDebugLog(this.accountList.selectedItem.account.id);
|
||||
},
|
||||
updateConnectedLabels: function am_updateConnectedLabels() {
|
||||
for (let i = 0; i < gAccountManager.accountList.itemCount; ++i) {
|
||||
let item = gAccountManager.accountList.getItemAtIndex(i);
|
||||
|
|
|
@ -52,6 +52,10 @@
|
|||
label="&account.copyDebugLog.label;"
|
||||
accesskey="&account.copyDebugLog.accesskey;"
|
||||
oncommand="gAccountManager.copyDebugLog();"/>
|
||||
<command id="cmd_showDebugLog"
|
||||
label="&account.showDebugLog.label;"
|
||||
accesskey="&account.showDebugLog.accesskey;"
|
||||
oncommand="gAccountManager.showDebugLog();"/>
|
||||
<command id="cmd_moveup"
|
||||
label="&account.moveup.label;"
|
||||
oncommand="gAccountManager.moveCurrentItem(-1)"/>
|
||||
|
@ -104,6 +108,8 @@
|
|||
observes="contextAccountsItems"/>
|
||||
<menuitem id="context_copyDebugLog"
|
||||
command="cmd_copyDebugLog"/>
|
||||
<menuitem id="context_showDebugLog"
|
||||
command="cmd_showDebugLog"/>
|
||||
<menuseparator id="context_accountsItemsSeparator"
|
||||
observes="contextAccountsItems"/>
|
||||
<menuitem command="cmd_new"/>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link href="chrome://instantbird/skin/debugLog.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,175 @@
|
|||
<?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/. -->
|
||||
|
||||
<bindings id="debugLogPanelBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<binding id="debugLogPanel">
|
||||
<resources>
|
||||
<stylesheet src="chrome://instantbird/skin/debugLogPanel.css"/>
|
||||
</resources>
|
||||
|
||||
<content flex="1">
|
||||
<xul:vbox flex="1">
|
||||
<xul:toolbar class="debugLogTab-toolbar">
|
||||
<xul:menulist class="accountList" anonid="accountList" flex="1"
|
||||
onselect="document.getBindingParent(this).onAccountSelect()"/>
|
||||
<xul:toolbarbutton class="debugLogTab-button" anonid="refreshButton"
|
||||
label="Refresh"
|
||||
oncommand="document.getBindingParent(this).showDebugLog();"/>
|
||||
<xul:toolbarbutton class="debugLogTab-button" anonid="copyButton"
|
||||
label="Copy"
|
||||
oncommand="document.getBindingParent(this).copyDebugLog()"/>
|
||||
</xul:toolbar>
|
||||
<xul:browser anonid="debugLogBrowser" disablehistory="true" type="content"
|
||||
flex="1" src="chrome://instantbird/content/debugLog.html"/>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<property name="browser" readonly="true">
|
||||
<getter>
|
||||
return document.getAnonymousElementByAttribute(this, "anonid", "debugLogBrowser");
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<property name="accountList" readonly="true">
|
||||
<getter>
|
||||
return document.getAnonymousElementByAttribute(this, "anonid", "accountList");
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<!-- Only show the debug log if the account list is already populated. This
|
||||
is useful, for example, if we are importing into a new window and only
|
||||
need to repopulate the account list without re-displaying the log. -->
|
||||
<method name="onAccountSelect">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this._accountListInited)
|
||||
this.showDebugLog();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- This method populates the list of accounts and ensures the specified
|
||||
account is selected. Since the _inited flag is set here before returning,
|
||||
no debug log will be shown. -->
|
||||
<method name="initAccountList">
|
||||
<parameter name="aAccountId"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!("Services" in window))
|
||||
Components.utils.import("resource:///modules/imServices.jsm");
|
||||
let accounts = Services.accounts.getAccounts();
|
||||
while (accounts.hasMoreElements()) {
|
||||
let acc = accounts.getNext();
|
||||
var proto = acc.protocol;
|
||||
var item = this.accountList.appendItem(acc.name, acc.id, proto.name);
|
||||
item.setAttribute("image", proto.iconBaseURI + "icon.png");
|
||||
item.setAttribute("class", "menuitem-iconic");
|
||||
let accId = acc.id;
|
||||
item.accountId = accId;
|
||||
if (accId == aAccountId)
|
||||
this.accountList.selectedItem = item;
|
||||
}
|
||||
this._accountListInited = true;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="copyDebugLog">
|
||||
<body>
|
||||
<![CDATA[
|
||||
Components.classes["@mozilla.org/widget/clipboardhelper;1"]
|
||||
.getService(Components.interfaces.nsIClipboardHelper)
|
||||
.copyString(this.browser.contentDocument.body.textContent);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="showDebugLog">
|
||||
<body>
|
||||
<![CDATA[
|
||||
let accId = this.accountList.selectedItem.accountId;
|
||||
let account = Services.accounts.getAccountById(accId);
|
||||
this.tab.setAttribute("label", "Debug log for " + account.name);
|
||||
let doc = this.browser.contentDocument;
|
||||
let table = doc.createElement("table");
|
||||
table.style = "width: 100%";
|
||||
// Clear out any existing content before appending the table.
|
||||
doc.body.innerHTML = "";
|
||||
doc.body.appendChild(table);
|
||||
for (let dbgMsg of account.getDebugMessages()) {
|
||||
let m = dbgMsg.message;
|
||||
const dateServ = Cc["@mozilla.org/intl/scriptabledateformat;1"]
|
||||
.getService(Ci.nsIScriptableDateFormat);
|
||||
let time = new Date(m.timeStamp);
|
||||
time = dateServ.FormatDateTime("", dateServ.dateFormatShort,
|
||||
dateServ.timeFormatSeconds,
|
||||
time.getFullYear(), time.getMonth() + 1,
|
||||
time.getDate(), time.getHours(),
|
||||
time.getMinutes(), time.getSeconds());
|
||||
let level = dbgMsg.logLevel;
|
||||
let rowClass = "default";
|
||||
let formattedMsg;
|
||||
if (!level)
|
||||
formattedMsg = "(" + m.errorMessage + ")";
|
||||
else {
|
||||
if (level == dbgMsg.LEVEL_ERROR) {
|
||||
level = "ERROR";
|
||||
rowClass = "error";
|
||||
}
|
||||
else if (level == dbgMsg.LEVEL_WARNING) {
|
||||
level = "WARN.";
|
||||
rowClass = "warn";
|
||||
}
|
||||
else if (level == dbgMsg.LEVEL_LOG) {
|
||||
level = "LOG ";
|
||||
rowClass = "log";
|
||||
}
|
||||
else {
|
||||
level = "DEBUG";
|
||||
rowClass = "debug";
|
||||
}
|
||||
formattedMsg = level + " (@ " + m.sourceLine +
|
||||
" " + m.sourceName + ":" + m.lineNumber + ")\n" +
|
||||
m.errorMessage;
|
||||
}
|
||||
let tr = doc.createElement("tr");
|
||||
tr.className = rowClass;
|
||||
let timeCell = doc.createElement("td");
|
||||
timeCell.className = "time";
|
||||
let msgCell = doc.createElement("td");
|
||||
msgCell.className = "msg";
|
||||
// The trailing space and newline are necessary to ensure correct
|
||||
// formatting when text is selected/copied.
|
||||
timeCell.textContent = "[" + time + "] ";
|
||||
msgCell.textContent = formattedMsg + "\n";
|
||||
tr.appendChild(timeCell);
|
||||
tr.appendChild(msgCell);
|
||||
table.appendChild(tr);
|
||||
}
|
||||
// Ensure the scroll position is reset.
|
||||
doc.body.scrollTop = 0;
|
||||
doc.body.scrollLeft = 0;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="finishImport">
|
||||
<parameter name="aDebugLogPanel"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
this.browser.swapDocShells(aDebugLogPanel.browser);
|
||||
this.initAccountList(aDebugLogPanel.accountList.selectedItem.accountId);
|
||||
this.tab.setAttribute("label", aDebugLogPanel.tab.getAttribute("label"));
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
</bindings>
|
|
@ -14,6 +14,10 @@ newtab {
|
|||
-moz-binding: url("chrome://instantbird/content/newtab.xml#newtab-item");
|
||||
}
|
||||
|
||||
debugLogPanel {
|
||||
-moz-binding: url("chrome://instantbird/content/debugLogPanel.xml#debugLogPanel")
|
||||
}
|
||||
|
||||
aboutPanel {
|
||||
-moz-binding: url("chrome://instantbird/content/aboutPanel.xml#aboutPanel");
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ instantbird.jar:
|
|||
content/instantbird/conversation.xml
|
||||
content/instantbird/conv.xml
|
||||
content/instantbird/credits.xhtml
|
||||
content/instantbird/debugLogPanel.xml
|
||||
content/instantbird/debugLog.html
|
||||
content/instantbird/engineManager.js
|
||||
content/instantbird/engineManager.xul
|
||||
content/instantbird/extensions.js
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
<!ENTITY account.cancelReconnection.accesskey "A">
|
||||
<!ENTITY account.copyDebugLog.label "Copy Debug Log">
|
||||
<!ENTITY account.copyDebugLog.accesskey "C">
|
||||
<!ENTITY account.showDebugLog.label "Show Debug Log">
|
||||
<!ENTITY account.showDebugLog.accesskey "H">
|
||||
<!ENTITY account.connecting "Connecting…">
|
||||
<!ENTITY account.disconnecting "Disconnecting…">
|
||||
<!ENTITY account.disconnected "Not Connected">
|
||||
|
|
|
@ -110,32 +110,18 @@ var Core = {
|
|||
Components.utils.reportError(e); // Log unexpected errors.
|
||||
return false;
|
||||
}
|
||||
// Try to get the most recent conversation window. If no such window exists,
|
||||
// win will be null.
|
||||
let win = Services.wm.getMostRecentWindow("Messenger:convs");
|
||||
// Tries to open an aboutPanel in the specified window.
|
||||
let showPage = function(aWindow, aPage) {
|
||||
// Return false if the window doesn't exist.
|
||||
if (!aWindow)
|
||||
return false;
|
||||
let panel = aWindow.document.createElementNS(
|
||||
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
||||
"aboutPanel");
|
||||
// Try to add the panel, and return false if the window couldn't accept
|
||||
// it (e.g. tabbed conversations are disabled).
|
||||
if (!aWindow.getTabBrowser().addPanel(panel))
|
||||
return false;
|
||||
panel.showAboutPage(aPage);
|
||||
aWindow.getTabBrowser().selectPanel(panel);
|
||||
return true;
|
||||
}
|
||||
// Try to show the page in win, and open a new window if it didn't work.
|
||||
if (!showPage(win, page)) {
|
||||
win = Services.ww.openWindow(null, "chrome://instantbird/content/instantbird.xul",
|
||||
"_blank", "chrome,toolbar,resizable", null);
|
||||
win.addEventListener("load", showPage.bind(null, win, page));
|
||||
self.showTab("aboutPanel", aPanel => aPanel.showAboutPage(page));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
Services.cmd.registerCommand({
|
||||
name: "debug",
|
||||
get helpString() self.bundle("debugCommnad.help"),
|
||||
usageContext: Ci.imICommand.CMD_CONTEXT_ALL,
|
||||
priority: Ci.imICommand.CMD_PRIORITY_DEFAULT,
|
||||
run: (aMsg, aConv) => {
|
||||
this.showDebugLog(aConv.account.id);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
@ -144,6 +130,15 @@ var Core = {
|
|||
return true;
|
||||
},
|
||||
|
||||
showDebugLog: function(aAccountId) {
|
||||
this.showTab("debugLogPanel", aPanel => {
|
||||
aPanel.browser.addEventListener("DOMContentLoaded", () => {
|
||||
aPanel.initAccountList(aAccountId);
|
||||
aPanel.showDebugLog();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
showWindow: function(aWindowType, aUrl, aName, aFeatures) {
|
||||
var win = Services.wm.getMostRecentWindow(aWindowType);
|
||||
if (win)
|
||||
|
@ -192,6 +187,38 @@ var Core = {
|
|||
prompter.checkForUpdates();
|
||||
},
|
||||
|
||||
// Creates a panel from the given binding name, and opens it in a new tab,
|
||||
// creating a new window if necessary. The callback is invoked after adding
|
||||
// the panel, which is passed as a parameter.
|
||||
showTab: function(aPanelName, aCallback) {
|
||||
// Try to get the most recent conversation window. If no such window exists,
|
||||
// win will be null.
|
||||
let win = Services.wm.getMostRecentWindow("Messenger:convs");
|
||||
// Tries to open the panel in the specified window.
|
||||
let showPanel = function(aWindow) {
|
||||
// Return false if the window doesn't exist.
|
||||
if (!aWindow)
|
||||
return false;
|
||||
let panel = aWindow.document.createElementNS(
|
||||
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
||||
aPanelName);
|
||||
// Try to add the panel, and return false if the window couldn't accept
|
||||
// it (e.g. tabbed conversations are disabled).
|
||||
if (!aWindow.getTabBrowser().addPanel(panel))
|
||||
return false;
|
||||
aWindow.getTabBrowser().selectPanel(panel);
|
||||
panel.ownerDocument.defaultView.focus();
|
||||
aCallback(panel);
|
||||
return true;
|
||||
}
|
||||
// Try to show the debug logs in win, and open a new window if it didn't work.
|
||||
if (showPanel(win))
|
||||
return;
|
||||
win = Services.ww.openWindow(null, "chrome://instantbird/content/instantbird.xul",
|
||||
"_blank", "chrome,toolbar,resizable", null);
|
||||
win.addEventListener("load", showPanel.bind(null, win));
|
||||
},
|
||||
|
||||
getIter: function(aEnumerator) {
|
||||
while (aEnumerator.hasMoreElements())
|
||||
yield aEnumerator.getNext();
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/* 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/. */
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
tr {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
tr.debug {
|
||||
background-color: #ecffe0;
|
||||
}
|
||||
|
||||
tr.log {
|
||||
background-color: #d3edff;
|
||||
}
|
||||
|
||||
tr.warn {
|
||||
background-color: #f8f3cc;
|
||||
}
|
||||
|
||||
tr.error {
|
||||
background-color: #ffd0dc;
|
||||
}
|
||||
|
||||
td.time {
|
||||
white-space: nowrap;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
td.msg {
|
||||
white-space: pre-wrap;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/* 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/. */
|
||||
|
||||
.debugLogTab-button {
|
||||
-moz-appearance: toolbarbutton;
|
||||
}
|
||||
|
||||
.debugLogTab-toolbar {
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
border-style: none;
|
||||
-moz-appearance: none;
|
||||
%ifdef XP_MACOSX
|
||||
background-color: -moz-mac-chrome-active;
|
||||
background-image: -moz-linear-gradient(rgba(255,255,255,.43), rgba(255,255,255,0));
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.57);
|
||||
}
|
||||
|
||||
.debugLogTab-toolbar:-moz-window-inactive {
|
||||
background-color: -moz-mac-chrome-inactive;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.32);
|
||||
%else
|
||||
background-color: -moz-Dialog;
|
||||
%ifdef XP_WIN
|
||||
background-image: -moz-linear-gradient(rgba(255,255,255,.5), rgba(255,255,255,0));
|
||||
%else
|
||||
background-image: -moz-linear-gradient(rgba(255,255,255,.3), rgba(255,255,255,0));
|
||||
%endif
|
||||
border-bottom: 1px solid ThreeDShadow;
|
||||
%endif
|
||||
}
|
|
@ -16,6 +16,8 @@ instantbird.jar:
|
|||
* skin/classic/instantbird/richlistbox.css
|
||||
* skin/classic/instantbird/accountWizard.css
|
||||
* skin/classic/instantbird/newtab.css
|
||||
skin/classic/instantbird/debugLog.css
|
||||
* skin/classic/instantbird/debugLogPanel.css
|
||||
skin/classic/instantbird/newConversation.png
|
||||
skin/classic/instantbird/founder.png
|
||||
skin/classic/instantbird/operator.png
|
||||
|
|
Загрузка…
Ссылка в новой задаче