From 13ab3bd87f4f8ba17ef2bd630cbbdddb2370e28c Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Sun, 3 Dec 2023 04:43:25 -0500 Subject: [PATCH] fx115: Add command-line handling to Firefox command-line handler XPCOM objects have to be statically registered now, so instead of creating our own command-line handler, just stuff our code into the Firefox one. A few parameters require the Zotero object, which isn't available in the Firefox CLH, so I've left those in zotero-service.js for now until we decide how to deal with those. --- app/assets/commandLineHandler.js | 90 +++++++++++++++++++ app/build.sh | 18 ++++ chrome.manifest | 4 - .../zotero/modules/commandLineOptions.mjs | 22 +++++ chrome/content/zotero/xpcom/dataDirectory.js | 4 +- chrome/content/zotero/xpcom/zotero.js | 2 +- components/zotero-service.js | 63 ------------- 7 files changed, 133 insertions(+), 70 deletions(-) create mode 100644 app/assets/commandLineHandler.js create mode 100644 chrome/content/zotero/modules/commandLineOptions.mjs diff --git a/app/assets/commandLineHandler.js b/app/assets/commandLineHandler.js new file mode 100644 index 0000000000..fa7c1d7d32 --- /dev/null +++ b/app/assets/commandLineHandler.js @@ -0,0 +1,90 @@ +let { CommandLineOptions, TestOptions } = ChromeUtils.importESModule("chrome://zotero/content/modules/commandLineOptions.mjs"); + +// Force debug output to window +if (cmdLine.handleFlag("ZoteroDebug", false)) { + CommandLineOptions.forceDebugLog = 2; +} +// Force debug output to text console +else if (cmdLine.handleFlag("ZoteroDebugText", false)) { + CommandLineOptions.forceDebugLog = 1; +} +// Pressing Ctrl-C via the terminal is interpreted as a crash, and after three crashes +// Firefox starts up in automatic safe mode (troubleshooting mode). To avoid this, we clear the crash +// counter when using one of the debug-logging flags, which generally imply terminal usage. +if (CommandLineOptions.forceDebugLog) { + Services.prefs.getBranch("toolkit.startup.").clearUserPref("recent_crashes"); +} + +CommandLineOptions.forceDataDir = cmdLine.handleFlagWithParam("datadir", false); + +var processTestOptions = false; +if (cmdLine.handleFlag("ZoteroTest", false)) { + CommandLineOptions.test = true; + processTestOptions = true; +} +if (cmdLine.handleFlag("ZoteroAutomatedTest", false)) { + CommandLineOptions.automatedTest = true; +} +if (cmdLine.handleFlag("ZoteroSkipBundledFiles", false)) { + CommandLineOptions.skipBundledFiles = true; +} + +if (processTestOptions) { + TestOptions.tests = cmdLine.handleFlagWithParam("test", false); + TestOptions.noquit = cmdLine.handleFlag("noquit", false); + TestOptions.makeTestData = cmdLine.handleFlag("makeTestData", false); + TestOptions.noquit = !TestOptions.makeTestData && this.noquit; + TestOptions.runTests = !TestOptions.makeTestData; + TestOptions.bail = cmdLine.handleFlag("bail", false); + TestOptions.startAt = cmdLine.handleFlagWithParam("startAtTestFile", false); + TestOptions.stopAt = cmdLine.handleFlagWithParam("stopAtTestFile", false); + TestOptions.grep = cmdLine.handleFlagWithParam("grep", false); + TestOptions.timeout = cmdLine.handleFlagWithParam("ZoteroTestTimeout", false); + + Services.ww.openWindow( + null, + "chrome://zotero-unit/content/runtests.html", + "_blank", + "chrome,dialog=no,all", + Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray) + ); + cmdLine.preventDefault = true; +} + +if (cmdLine.handleFlag("debugger", false)) { + (async function () { + try { + let portOrPath = Services.prefs.getBranch('').getIntPref('devtools.debugger.remote-port'); + + const { DevToolsLoader } = ChromeUtils.import( + "resource://devtools/shared/loader/Loader.jsm" + ); + const loader = new DevToolsLoader({ + freshCompartment: true, + }); + const { DevToolsServer } = loader.require("devtools/server/devtools-server"); + const { SocketListener } = loader.require("devtools/shared/security/socket"); + + if (DevToolsServer.initialized) { + dump("Debugger server already initialized\n\n"); + return; + } + + DevToolsServer.init(); + DevToolsServer.registerAllActors(); + DevToolsServer.allowChromeProcess = true; + const socketOptions = { portOrPath }; + const listener = new SocketListener(DevToolsServer, socketOptions); + await listener.open(); + if (!DevToolsServer.listeningSockets) { + throw new Error("No listening sockets"); + } + + dump(`Debugger server started on ${portOrPath}\n\n`); + } + catch (e) { + dump(e + "\n\n"); + Components.utils.reportError(e); + } + })(); +} diff --git a/app/build.sh b/app/build.sh index e4ed92af6d..dea8e0c641 100755 --- a/app/build.sh +++ b/app/build.sh @@ -54,6 +54,19 @@ function cleanup { } trap cleanup EXIT +function replace_line { + pattern=$1 + replacement=$2 + file=$3 + + if egrep -q "$pattern" "$file"; then + perl -pi -e "s/$pattern/$replacement/" "$file" + else + echo "$pattern" not found in "$file" -- aborting 2>&1 + exit 1 + fi +} + function abspath { echo $(cd $(dirname $1); pwd)/$(basename $1); } @@ -366,6 +379,11 @@ done echo "" >> chrome.manifest cat "$CALLDIR/assets/chrome.manifest" >> chrome.manifest +replace_line 'handle: function bch_handle\(cmdLine\) {' 'handle: function bch_handle(cmdLine) { + \/\/ TEST_OPTIONS_PLACEHOLDER + ' modules/BrowserContentHandler.sys.mjs +export CALLDIR && perl -pi -e 'BEGIN { local $/; open $fh, "$ENV{CALLDIR}/assets/commandLineHandler.js"; $replacement = <$fh>; close $fh; } s/\/\/ TEST_OPTIONS_PLACEHOLDER/$replacement/' modules/BrowserContentHandler.sys.mjs + # Move test files to root directory if [ $include_tests -eq 1 ]; then cat test/chrome.manifest >> chrome.manifest diff --git a/chrome.manifest b/chrome.manifest index 987caef622..8f3cefea97 100644 --- a/chrome.manifest +++ b/chrome.manifest @@ -63,10 +63,6 @@ locale zotero zh-TW chrome/locale/zh-TW/zotero/ skin zotero default chrome/skin/default/zotero/ -component {531828f8-a16c-46be-b9aa-14845c3b010f} components/zotero-service.js -contract @mozilla.org/browser/clh;1 {531828f8-a16c-46be-b9aa-14845c3b010f} -category command-line-handler m-zotero @mozilla.org/browser/clh;1 - component {06a2ed11-d0a4-4ff0-a56f-a44545eee6ea} components/zotero-autocomplete.js contract @mozilla.org/autocomplete/search;1?name=zotero {06a2ed11-d0a4-4ff0-a56f-a44545eee6ea} diff --git a/chrome/content/zotero/modules/commandLineOptions.mjs b/chrome/content/zotero/modules/commandLineOptions.mjs new file mode 100644 index 0000000000..cf2cb3f361 --- /dev/null +++ b/chrome/content/zotero/modules/commandLineOptions.mjs @@ -0,0 +1,22 @@ +// Used by commandLineHandler.js to store parameters from the command line + +export var CommandLineOptions = { + forceDebugLog: 0, + forceDataDir: false, + test: false, + automatedTest: false, + skipBundledFiles: false, +}; + +export var TestOptions = { + tests: false, + noquit: false, + makeTestData: false, + noquit: false, + runTests: false, + bail: false, + startAt: false, + stopAt: false, + grep: false, + timeout: false, +}; diff --git a/chrome/content/zotero/xpcom/dataDirectory.js b/chrome/content/zotero/xpcom/dataDirectory.js index e5c8f6cc5b..1789307d1f 100644 --- a/chrome/content/zotero/xpcom/dataDirectory.js +++ b/chrome/content/zotero/xpcom/dataDirectory.js @@ -39,8 +39,8 @@ Zotero.DataDirectory = { get defaultDir() { // Use special data directory for tests - if (Zotero.test) { - return OS.Path.join(OS.Path.dirname(OS.Constants.Path.profileDir), "Zotero"); + if (CommandLineOptions.test) { + return OS.Path.join(PathUtils.parent(OS.Constants.Path.profileDir), "Zotero"); } return OS.Path.join(OS.Constants.Path.homeDir, ZOTERO_CONFIG.CLIENT_NAME); }, diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js index 228e3728c8..a53b3ce743 100644 --- a/chrome/content/zotero/xpcom/zotero.js +++ b/chrome/content/zotero/xpcom/zotero.js @@ -36,7 +36,7 @@ const { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm XPCOMUtils.defineLazyModuleGetters(globalThis, { AsyncShutdown: "resource://gre/modules/AsyncShutdown.jsm", }); - +const { CommandLineOptions } = ChromeUtils.importESModule("chrome://zotero/content/modules/commandLineOptions.mjs"); Services.scriptloader.loadSubScript("resource://zotero/polyfill.js"); /* diff --git a/components/zotero-service.js b/components/zotero-service.js index cb4cafef57..385891155c 100644 --- a/components/zotero-service.js +++ b/components/zotero-service.js @@ -34,33 +34,6 @@ function ZoteroCommandLineHandler() {} ZoteroCommandLineHandler.prototype = { /* nsICommandLineHandler */ handle: async function (cmdLine) { - // Force debug output to window - if (cmdLine.handleFlag("ZoteroDebug", false)) { - zInitOptions.forceDebugLog = 2; - } - // Force debug output to text console - else if (cmdLine.handleFlag("ZoteroDebugText", false)) { - zInitOptions.forceDebugLog = 1; - } - // Pressing Ctrl-C via the terminal is interpreted as a crash, and after three crashes - // Firefox starts up in automatic safe mode (troubleshooting mode). To avoid this, we clear the crash - // counter when using one of the debug-logging flags, which generally imply terminal usage. - if (zInitOptions.forceDebugLog) { - Services.prefs.getBranch("toolkit.startup.").clearUserPref('recent_crashes'); - } - - zInitOptions.forceDataDir = cmdLine.handleFlagWithParam("datadir", false); - - if (cmdLine.handleFlag("ZoteroTest", false)) { - zInitOptions.test = true; - } - if (cmdLine.handleFlag("ZoteroAutomatedTest", false)) { - zInitOptions.automatedTest = true; - } - if (cmdLine.handleFlag("ZoteroSkipBundledFiles", false)) { - zInitOptions.skipBundledFiles = true; - } - // handler for Zotero integration commands // this is typically used on Windows only, via WM_COPYDATA rather than the command line var agent = cmdLine.handleFlagWithParam("ZoteroIntegrationAgent", false); @@ -108,42 +81,6 @@ ZoteroCommandLineHandler.prototype = { } } - param = cmdLine.handleFlag("debugger", false); - if (param) { - try { - let portOrPath = Services.prefs.getBranch('').getIntPref('devtools.debugger.remote-port'); - - const { DevToolsLoader } = ChromeUtils.import( - "resource://devtools/shared/loader/Loader.jsm" - ); - const loader = new DevToolsLoader({ - freshCompartment: true, - }); - const { DevToolsServer } = loader.require("devtools/server/devtools-server"); - const { SocketListener } = loader.require("devtools/shared/security/socket"); - - if (DevToolsServer.initialized) { - dump("Debugger server already initialized\n\n"); - return; - } - - DevToolsServer.init(); - DevToolsServer.registerAllActors(); - DevToolsServer.allowChromeProcess = true; - const socketOptions = { portOrPath }; - const listener = new SocketListener(DevToolsServer, socketOptions); - await listener.open(); - if (!DevToolsServer.listeningSockets) { - throw new Error("No listening sockets"); - } - - dump(`Debugger server started on ${portOrPath}\n\n`); - } - catch (e) { - dump(e + "\n\n"); - Components.utils.reportError(e); - } - } // In Fx49-based Mac Standalone, if Zotero is closed, an associated file is launched, and // Zotero hasn't been opened before, a -file parameter is passed and two main windows open.