Move debug output logging to the Help menu

Adds a submenu for quickly generating and submitting debug output, with
a button to copy the Debug ID to the clipboard and a one-click option to
restart with logging enabled. Debug output can also now be viewed in
real-time using the new debug output viewer window (previously available
only via a command-line flag).

The locale switcher has moved to the top of the Advanced prefpane (where
Debug Output Logging used to go) in a Miscellaneous section, and there's
a new "Advanced Configuration" section (mirroring Thunderbird) at the
bottom for "Config Editor".

Closes #1108
This commit is contained in:
Dan Stillman 2017-07-25 02:36:33 -04:00
parent e3947e7b45
commit c2bb4ac10b
8 changed files with 240 additions and 240 deletions

View file

@ -30,7 +30,6 @@ Zotero_Preferences.Advanced = {
init: function () {
Zotero_Preferences.Debug_Output.init();
Zotero_Preferences.Keys.init();
// Show Memory Info button if the Error Console menu option is enabled
@ -782,202 +781,6 @@ Zotero_Preferences.Attachment_Base_Directory = {
};
Zotero_Preferences.Debug_Output = {
_timer: null,
init: function () {
var storing = Zotero.Debug.storing;
this._updateButton();
this.updateLines();
if (storing) {
this._initTimer();
}
},
toggleStore: function () {
this.setStore(!Zotero.Debug.storing);
},
setStore: function (set) {
Zotero.Debug.setStore(set);
if (set) {
this._initTimer();
}
else {
if (this._timerID) {
this._timer.cancel();
this._timerID = null;
}
}
this._updateButton();
this.updateLines();
},
view: function () {
Zotero_Preferences.openInViewer("zotero://debug/");
},
submit: Zotero.Promise.coroutine(function* () {
document.getElementById('debug-output-submit').disabled = true;
var pm = document.getElementById('debug-output-submit-progress');
pm.hidden = false;
Components.utils.import("resource://zotero/config.js");
var url = ZOTERO_CONFIG.REPOSITORY_URL + "report?debug=1";
var output = yield Zotero.Debug.get(
Zotero.Prefs.get('debug.store.submitSize'),
Zotero.Prefs.get('debug.store.submitLineLength')
);
Zotero_Preferences.Debug_Output.setStore(false);
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
try {
var xmlhttp = yield Zotero.HTTP.request(
"POST",
url,
{
compressBody: true,
body: output,
logBodyLength: 30,
timeout: 30000,
requestObserver: function (req) {
// Don't fail during tests, with fake XHR
if (!req.channel) {
return;
}
req.channel.notificationCallbacks = {
onProgress: function (request, context, progress, progressMax) {
pm.mode = 'determined';
if (!pm.value || progress > pm.value) {
pm.value = progress;
}
if (!pm.max || progressMax > pm.max) {
pm.max = progressMax;
}
},
// nsIInterfaceRequestor
getInterface: function (iid) {
try {
return this.QueryInterface(iid);
}
catch (e) {
throw Components.results.NS_NOINTERFACE;
}
},
QueryInterface: function(iid) {
if (iid.equals(Components.interfaces.nsISupports) ||
iid.equals(Components.interfaces.nsIInterfaceRequestor) ||
iid.equals(Components.interfaces.nsIProgressEventSink)) {
return this;
}
throw Components.results.NS_NOINTERFACE;
},
}
}
}
);
}
catch (e) {
Zotero.logError(e);
let title = Zotero.getString('general.error');
let msg;
if (e instanceof Zotero.HTTP.UnexpectedStatusException) {
msg = Zotero.getString('general.invalidResponseServer');
}
else if (e instanceof Zotero.HTTP.BrowserOfflineException) {
msg = Zotero.getString('general.browserIsOffline', Zotero.appName);
}
else {
msg = Zotero.getString('zotero.preferences.advanced.debug.error');
}
ps.alert(null, title, msg);
return false;
}
document.getElementById('debug-output-submit').disabled = false;
document.getElementById('debug-output-submit-progress').hidden = true;
Zotero.debug(xmlhttp.responseText);
var reported = xmlhttp.responseXML.getElementsByTagName('reported');
if (reported.length != 1) {
ps.alert(
null,
Zotero.getString('general.error'),
Zotero.getString('general.serverError')
);
return false;
}
var reportID = reported[0].getAttribute('reportID');
ps.alert(
null,
Zotero.getString('zotero.preferences.advanced.debug.title'),
Zotero.getString('zotero.preferences.advanced.debug.sent', reportID)
);
return true;
}),
clear: function () {
Zotero.Debug.clear();
this.updateLines();
},
updateLines: function () {
var enabled = Zotero.Debug.storing;
var lines = Zotero.Debug.count();
document.getElementById('debug-output-lines').value = lines;
var empty = lines == 0;
document.getElementById('debug-output-view').disabled = !enabled && empty;
document.getElementById('debug-output-clear').disabled = empty;
document.getElementById('debug-output-submit').disabled = empty;
},
_initTimer: function () {
this._timer = Components.classes["@mozilla.org/timer;1"].
createInstance(Components.interfaces.nsITimer);
this._timer.initWithCallback({
notify: function() {
Zotero_Preferences.Debug_Output.updateLines();
}
}, 10000, Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
},
_updateButton: function () {
var storing = Zotero.Debug.storing
var button = document.getElementById('debug-output-enable');
if (storing) {
button.label = Zotero.getString('general.disable');
}
else {
button.label = Zotero.getString('general.enable');
}
},
onUnload: function () {
if (this._timer) {
this._timer.cancel();
}
}
};
Zotero_Preferences.Keys = {
init: function () {
var rows = document.getElementById('zotero-prefpane-advanced-keys-tab').getElementsByTagName('row');

View file

@ -71,26 +71,15 @@
<tabpanels id="zotero-prefpane-advanced-tabpanels">
<tabpanel id="zotero-prefpane-advanced-general-tab" orient="vertical">
<groupbox>
<caption label="&zotero.preferences.debugOutputLogging;"/>
<!-- This doesn't wrap without an explicit width -->
<vbox>
<description width="45em">&zotero.preferences.debugOutputLogging.message;</description>
</vbox>
<groupbox id="zotero-prefpane-advanced-miscellaneous">
<caption label="&zotero.preferences.miscellaneous;"/>
<hbox align="center">
<button id="debug-output-enable" oncommand="Zotero_Preferences.Debug_Output.toggleStore()"/>
<label id="debug-output-lines" style="margin-right: 0"/>
<label value="&zotero.preferences.debugOutputLogging.linesLogged;"/>
<checkbox preference="pref-debug-output-enableAfterRestart" label="&zotero.preferences.debugOutputLogging.enableAfterRestart;" style="margin-left: 1.5em"/>
</hbox>
<hbox align="center">
<button id="debug-output-view" label="&zotero.preferences.debugOutputLogging.viewOutput;" oncommand="Zotero_Preferences.Debug_Output.view()"/>
<button id="debug-output-clear" label="&zotero.preferences.debugOutputLogging.clearOutput;" oncommand="Zotero_Preferences.Debug_Output.clear()"/>
<button id="debug-output-submit" label="&zotero.preferences.debugOutputLogging.submitToServer;" oncommand="Zotero_Preferences.Debug_Output.submit()"/>
<progressmeter id="debug-output-submit-progress" mode="undetermined" hidden="true"/>
<label value="&zotero.bibliography.locale.label;"/>
<menulist id="locale-menu"
oncommand="Zotero_Preferences.Advanced.onLocaleChange()">
<menupopup/>
</menulist>
</hbox>
</groupbox>
@ -131,18 +120,8 @@
</hbox>
</groupbox>
<groupbox id="zotero-prefpane-advanced-miscellaneous">
<caption label="&zotero.preferences.miscellaneous;"/>
<hbox align="center">
<label value="&zotero.bibliography.locale.label;"/>
<menulist id="locale-menu"
oncommand="Zotero_Preferences.Advanced.onLocaleChange()">
<menupopup/>
</menulist>
</hbox>
<separator/>
<groupbox id="zotero-prefpane-advanced-advancedConfiguration">
<caption label="&zotero.preferences.advanced.advancedConfiguration;"/>
<hbox id="zotero-prefpane-advanced-openbuttons" align="center" style="display: block">
<button id="config-editor"

View file

@ -52,6 +52,8 @@ const ZoteroStandalone = new function() {
document.getElementById('menu_errorConsole').hidden = false;
}
ZoteroStandalone.DebugOutput.init();
Zotero.hideZoteroPaneOverlays();
ZoteroPane.init();
ZoteroPane.makeVisible();
@ -197,6 +199,189 @@ const ZoteroStandalone = new function() {
}
}
ZoteroStandalone.DebugOutput = {
_timer: null,
init: function () {
var storing = Zotero.Debug.storing;
this._showMenu();
this.update();
},
toggleStore: function () {
Zotero.Debug.setStore(!Zotero.Debug.storing);
},
update: function () {
var enabled = Zotero.Debug.storing;
var lines = Zotero.Debug.count();
var empty = lines == 0;
// Show "Submit" when enabled, but leave disabled until there's output
var menuitem = document.getElementById('debug-output-submit');
menuitem.hidden = !enabled && empty;
menuitem.disabled = empty;
// Toggle between "Enable" and "Disable"
menuitem = document.getElementById('debug-output-enable-disable');
menuitem.label = Zotero.getString('general.' + (enabled ? 'disable' : 'enable'));
// Update line count
var str = Zotero.getString('zotero.debugOutputLogging.linesLogged', lines, lines);
document.getElementById('debug-output-status').label = str;
// Enable "Clear" when there's output
document.getElementById('debug-output-clear').disabled = empty;
},
submit: function () {
// 'Zotero' isn't defined yet when this function is created, so do it inline
return Zotero.Promise.coroutine(function* () {
Components.utils.import("resource://zotero/config.js");
var url = ZOTERO_CONFIG.REPOSITORY_URL + "report?debug=1";
var output = yield Zotero.Debug.get(
Zotero.Prefs.get('debug.store.submitSize'),
Zotero.Prefs.get('debug.store.submitLineLength')
);
Zotero.Debug.setStore(false);
var ps = Services.prompt;
try {
var xmlhttp = yield Zotero.HTTP.request(
"POST",
url,
{
compressBody: true,
body: output,
logBodyLength: 30,
timeout: 15000,
requestObserver: function (req) {
// Don't fail during tests, with fake XHR
if (!req.channel) {
return;
}
req.channel.notificationCallbacks = {
onProgress: function (request, context, progress, progressMax) {},
// nsIInterfaceRequestor
getInterface: function (iid) {
try {
return this.QueryInterface(iid);
}
catch (e) {
throw Components.results.NS_NOINTERFACE;
}
},
QueryInterface: function(iid) {
if (iid.equals(Components.interfaces.nsISupports) ||
iid.equals(Components.interfaces.nsIInterfaceRequestor) ||
iid.equals(Components.interfaces.nsIProgressEventSink)) {
return this;
}
throw Components.results.NS_NOINTERFACE;
},
}
}
}
);
}
catch (e) {
Zotero.logError(e);
let title = Zotero.getString('general.error');
let msg;
if (e instanceof Zotero.HTTP.UnexpectedStatusException) {
msg = Zotero.getString('general.invalidResponseServer');
}
else if (e instanceof Zotero.HTTP.BrowserOfflineException) {
msg = Zotero.getString('general.browserIsOffline', Zotero.appName);
}
else {
msg = Zotero.getString('zotero.debugOutputLogging.dialog.error');
}
ps.alert(null, title, msg);
return false;
}
Zotero.debug(xmlhttp.responseText);
var reported = xmlhttp.responseXML.getElementsByTagName('reported');
if (reported.length != 1) {
ps.alert(
null,
Zotero.getString('general.error'),
Zotero.getString('general.serverError')
);
return false;
}
var reportID = reported[0].getAttribute('reportID');
var buttonFlags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING
+ ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL;
var index = ps.confirmEx(
null,
Zotero.getString('zotero.debugOutputLogging.dialog.title'),
Zotero.getString('zotero.debugOutputLogging.dialog.sent', [ZOTERO_CONFIG.DOMAIN_NAME, reportID]),
buttonFlags,
Zotero.getString('general.copyToClipboard'),
null, null, null, {}
);
if (index == 0) {
const helper = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
.getService(Components.interfaces.nsIClipboardHelper);
helper.copyString("D" + reportID);
}
Zotero.Debug.clear();
return true;
}.bind(this))();
},
view: function () {
Zotero.openInViewer("chrome://zotero/content/debugViewer.html", function (doc) {
var submitted = false;
doc.querySelector('#submit-button').addEventListener('click', function (event) {
submitted = true;
});
doc.querySelector('#clear-button').addEventListener('click', function (event) {
Zotero.Debug.clear();
});
// If output has been submitted, disable logging when window is closed
doc.defaultView.addEventListener('unload', function (event) {
if (submitted) {
Zotero.Debug.setStore(false);
Zotero.Debug.clear();
}
});
});
},
clear: function () {
Zotero.Debug.clear();
},
restartEnabled: function () {
Zotero.Prefs.set('debug.store', true);
Zotero.Utilities.Internal.quit(true);
},
_showMenu: function () {
document.getElementById('debug-output-menu').hidden = false;
}
};
/** Taken from browser.js **/
function toJavaScriptConsole() {
toOpenWindowByType("global:console", "chrome://global/content/console.xul");

View file

@ -207,6 +207,34 @@
accesskey="&helpReportErrors.accesskey;"
label="&helpReportErrors.label;"
command="cmd_zotero_reportErrors"/>
<menu id="debug-output-menu"
accesskey="&debugOutputLogging.accesskey;"
label="&debugOutputLogging.label;"
hidden="true">
<menupopup id="debug-output-popup"
onpopupshowing="ZoteroStandalone.DebugOutput.update()">
<menuitem id="debug-output-submit"
label="&debugOutputLogging.submit;"
oncommand="ZoteroStandalone.DebugOutput.submit()"
hidden="true"/>
<menuitem id="debug-output-enable-disable"
oncommand="ZoteroStandalone.DebugOutput.toggleStore()"/>
<menuseparator/>
<menuitem id="debug-output-status" disabled="true"/>
<menuseparator/>
<menuitem id="debug-output-view"
label="&debugOutputLogging.view;"
oncommand="ZoteroStandalone.DebugOutput.view()"/>
<menuitem id="debug-output-clear"
label="&debugOutputLogging.clear;"
oncommand="ZoteroStandalone.DebugOutput.clear()"/>
<menuseparator/>
<menuitem id="debug-output-restart-enabled"
label="&debugOutputLogging.restartWithLoggingEnabled;"
oncommand="ZoteroStandalone.DebugOutput.restartEnabled()"/>
</menupopup>
</menu>
<menuseparator/>
<menuitem id="checkForUpdates"
accesskey="&helpCheckForUpdates.accesskey;"
label="&helpCheckForUpdates.label;"

View file

@ -38,7 +38,7 @@ Zotero.Debug = new function () {
* Debug logging can be set in several different ways:
*
* - via the debug.log pref in the client or connector
* - by enabling debug output logging in the Advanced prefs in the client
* - by enabling debug output logging from the Help menu
* - by passing -ZoteroDebug or -ZoteroDebugText on the command line
*
* In the client, debug.log and -ZoteroDebugText enable logging via the terminal, while -ZoteroDebug
@ -231,13 +231,14 @@ Zotero.Debug = new function () {
this.getConsoleViewerOutput = function () {
var queue = _consoleViewerQueue;
var queue = _output.concat(_consoleViewerQueue);
_consoleViewerQueue = [];
return queue;
}
this.addConsoleViewerListener = function (listener) {
this.enabled = _consoleViewer = true;
_consoleViewerListener = listener;
};

View file

@ -175,6 +175,8 @@
<!ENTITY zotero.preferences.advanced.filesAndFolders "Files and Folders">
<!ENTITY zotero.preferences.advanced.keys "Shortcuts">
<!ENTITY zotero.preferences.advanced.advancedConfiguration "Advanced Configuration">
<!ENTITY zotero.preferences.prefpane.locate "Locate">
<!ENTITY zotero.preferences.locate.locateEngineManager "Article Lookup Engine Manager">
<!ENTITY zotero.preferences.locate.description "Description">
@ -206,12 +208,4 @@
<!ENTITY zotero.preferences.dbMaintenance.resetTranslators "Reset Translators…">
<!ENTITY zotero.preferences.dbMaintenance.resetStyles "Reset Styles…">
<!ENTITY zotero.preferences.debugOutputLogging "Debug Output Logging">
<!ENTITY zotero.preferences.debugOutputLogging.message "Debug output can help Zotero developers diagnose problems in Zotero. Debug logging will slow down Zotero, so you should generally leave it disabled unless a Zotero developer requests debug output.">
<!ENTITY zotero.preferences.debugOutputLogging.linesLogged "lines logged">
<!ENTITY zotero.preferences.debugOutputLogging.enableAfterRestart "Enable after restart">
<!ENTITY zotero.preferences.debugOutputLogging.viewOutput "View Output">
<!ENTITY zotero.preferences.debugOutputLogging.clearOutput "Clear Output">
<!ENTITY zotero.preferences.debugOutputLogging.submitToServer "Submit to Zotero Server">
<!ENTITY zotero.preferences.configEditor "Config Editor">

View file

@ -75,5 +75,13 @@
<!ENTITY helpReportErrors.label "Report Errors…">
<!ENTITY helpReportErrors.accesskey "R">
<!ENTITY debugOutputLogging.label "Debug Output Logging">
<!ENTITY debugOutputLogging.accesskey "L">
<!ENTITY debugOutputLogging.submit "Submit Output">
<!ENTITY debugOutputLogging.view "View Output">
<!ENTITY debugOutputLogging.clear "Clear Output">
<!ENTITY debugOutputLogging.restartWithLoggingEnabled "Restart with Logging Enabled">
<!ENTITY helpCheckForUpdates.label "Check for Updates…">
<!ENTITY helpCheckForUpdates.accesskey "U">

View file

@ -62,6 +62,7 @@ general.tryAgain = Try Again
general.tryLater = Try Later
general.showDirectory = Show Directory
general.continue = Continue
general.copyToClipboard = Copy to Clipboard
general.operationInProgress = A Zotero operation is currently in progress.
general.operationInProgress.waitUntilFinished = Please wait until it has finished.
@ -672,9 +673,10 @@ zotero.preferences.advanced.migrateDataDir.directoryWillBeMoved = Your %1
zotero.preferences.advanced.migrateDataDir.appMustBeRestarted = %S must be restarted to complete the migration.
zotero.preferences.advanced.migrateDataDir.manualMigration = You can also quit %1$S and move your existing data directory to %2$S manually, which may be faster for larger data directories. %3$S will automatically detect the new location.
zotero.preferences.advanced.debug.title = Debug Output Submitted
zotero.preferences.advanced.debug.sent = Debug output has been sent to the Zotero server.\n\nThe Debug ID is D%S.
zotero.preferences.advanced.debug.error = An error occurred sending debug output.
zotero.debugOutputLogging.linesLogged = %1$S line logged;%1$S lines logged
zotero.debugOutputLogging.dialog.title = Debug Output Submitted
zotero.debugOutputLogging.dialog.sent = Debug output has been sent to %S.\n\nThe Debug ID is D%S.
zotero.debugOutputLogging.dialog.error = An error occurred sending debug output.
dragAndDrop.existingFiles = The following files already existed in the destination directory and were not copied:
dragAndDrop.filesNotFound = The following files were not found and could not be copied: