From 7276b8c50d754d878c09e34fece30f7fd845135c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adomas=20Ven=C4=8Dkauskas?= Date: Wed, 27 Mar 2024 11:54:53 +0200 Subject: [PATCH] fx115: Readd support for -file, -url and winword command line handlers --- app/assets/commandLineHandler.js | 6 + app/build.sh | 2 - .../zotero/modules/commandLineOptions.mjs | 2 + .../zotero/xpcom/commandLineHandler.js | 143 ++++++++++++++++++ chrome/content/zotero/xpcom/zotero.js | 2 + chrome/content/zotero/zotero.mjs | 1 + components/zotero-service.js | 140 ----------------- 7 files changed, 154 insertions(+), 142 deletions(-) create mode 100644 chrome/content/zotero/xpcom/commandLineHandler.js delete mode 100644 components/zotero-service.js diff --git a/app/assets/commandLineHandler.js b/app/assets/commandLineHandler.js index fa7c1d7d32..bd2cda150a 100644 --- a/app/assets/commandLineHandler.js +++ b/app/assets/commandLineHandler.js @@ -16,6 +16,12 @@ if (CommandLineOptions.forceDebugLog) { } CommandLineOptions.forceDataDir = cmdLine.handleFlagWithParam("datadir", false); +// Set here, to be acted upon in xpcom/commandLineHandler.js +CommandLineOptions.file = cmdLine.handleFlagWithParam("file", false); +CommandLineOptions.url = cmdLine.handleFlagWithParam("url", false); +if (CommandLineOptions.url) { + CommandLineOptions.url = cmdLine.resolveURI(CommandLineOptions.url); +} var processTestOptions = false; if (cmdLine.handleFlag("ZoteroTest", false)) { diff --git a/app/build.sh b/app/build.sh index dea8e0c641..19c92c2aba 100755 --- a/app/build.sh +++ b/app/build.sh @@ -266,8 +266,6 @@ fi # Merge preserved files from Firefox # # components -mv components/* components-fx -rmdir components mv components-fx components mv defaults defaults-z diff --git a/chrome/content/zotero/modules/commandLineOptions.mjs b/chrome/content/zotero/modules/commandLineOptions.mjs index cf2cb3f361..cfe3f4f3a2 100644 --- a/chrome/content/zotero/modules/commandLineOptions.mjs +++ b/chrome/content/zotero/modules/commandLineOptions.mjs @@ -6,6 +6,8 @@ export var CommandLineOptions = { test: false, automatedTest: false, skipBundledFiles: false, + file: false, + url: false, }; export var TestOptions = { diff --git a/chrome/content/zotero/xpcom/commandLineHandler.js b/chrome/content/zotero/xpcom/commandLineHandler.js new file mode 100644 index 0000000000..8f40cf689e --- /dev/null +++ b/chrome/content/zotero/xpcom/commandLineHandler.js @@ -0,0 +1,143 @@ +/* + ***** BEGIN LICENSE BLOCK ***** + + Copyright © 2009 Center for History and New Media + George Mason University, Fairfax, Virginia, USA + http://zotero.org + + This file is part of Zotero. + + Zotero is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Zotero is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with Zotero. If not, see . + + + Based on nsChromeExtensionHandler example code by Ed Anuff at + http://kb.mozillazine.org/Dev_:_Extending_the_Chrome_Protocol + + ***** END LICENSE BLOCK ***** +*/ + +Zotero.CommandLineIngester = { + ingest: async function () { + const { CommandLineOptions } = ChromeUtils.importESModule("chrome://zotero/content/modules/commandLineOptions.mjs"); + + var fileToOpen; + // Handle zotero:// and file URIs + var uri = CommandLineOptions.url; + if (uri) { + if (uri.schemeIs("zotero")) { + // Check for existing window and focus it + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + var win = wm.getMostRecentWindow("navigator:browser"); + if (win) { + win.focus(); + win.ZoteroPane.loadURI(uri.spec); + } + } + // See below + else if (uri.schemeIs("file")) { + fileToOpen = OS.Path.fromFileURI(uri.spec); + } + else { + Zotero.debug(`Not handling URL: ${uri.spec}\n\n`); + } + } + + + fileToOpen = fileToOpen || CommandLineOptions.file; + if (fileToOpen) { + var file = Zotero.File.pathToFile(fileToOpen); + + if (file.leafName.substr(-4).toLowerCase() === ".csl" + || file.leafName.substr(-8).toLowerCase() === ".csl.txt") { + // Install CSL file + Zotero.Styles.install({ file: file.path }, file.path); + } + else { + // Ask before importing + var checkState = { + value: Zotero.Prefs.get('import.createNewCollection.fromFileOpenHandler') + }; + if (Services.prompt.confirmCheck(null, Zotero.getString('ingester.importFile.title'), + Zotero.getString('ingester.importFile.text', [file.leafName]), + Zotero.getString('ingester.importFile.intoNewCollection'), + checkState)) { + Zotero.Prefs.set( + 'import.createNewCollection.fromFileOpenHandler', checkState.value + ); + + // Perform file import in front window + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + var browserWindow = wm.getMostRecentWindow("navigator:browser"); + browserWindow.Zotero_File_Interface.importFile({ + file, + createNewCollection: checkState.value + }); + } + } + } + + CommandLineOptions.url = false; + CommandLineOptions.file = false; + }, +}; + +/** + * The object representing the Zotero command line handler. + * It is only active after Zotero is initialized and there is initial handling + * in app/assets/commandLineHandler.js + */ +var ZoteroCommandLineHandler = { + /* nsICommandLineHandler */ + handle: async function (cmdLine) { + const { Zotero } = ChromeUtils.importESModule("chrome://zotero/content/zotero.mjs"); + // 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); + if (agent) { + // Don't open a new window + cmdLine.preventDefault = true; + + var command = cmdLine.handleFlagWithParam("ZoteroIntegrationCommand", false); + var docId = cmdLine.handleFlagWithParam("ZoteroIntegrationDocument", false); + var templateVersion = parseInt(cmdLine.handleFlagWithParam("ZoteroIntegrationTemplateVersion", false)); + templateVersion = isNaN(templateVersion) ? 0 : templateVersion; + + Zotero.Integration.execCommand(agent, command, docId, templateVersion); + } + + await Zotero.CommandLineIngester.ingest(); + }, + + classID: Components.ID("{531828f8-a16c-46be-b9aa-14845c3b010f}"), + contractID: "@zotero.org/command-line-handler;1", + QueryInterface: ChromeUtils.generateQI(["nsISupports", "nsICommandLineHandler"]), + createInstance(iid) { + return this.QueryInterface(iid); + }, +}; + +const Cm = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +Cm.registerFactory( + ZoteroCommandLineHandler.classID, + "command-line-handler", + ZoteroCommandLineHandler.contractID, + ZoteroCommandLineHandler +); +const catman = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager); + +catman.addCategoryEntry("command-line-handler", + "m-zotero", + ZoteroCommandLineHandler.contractID, false, true); diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js index 1d682f7750..24df147580 100644 --- a/chrome/content/zotero/xpcom/zotero.js +++ b/chrome/content/zotero/xpcom/zotero.js @@ -416,6 +416,8 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js"); Zotero.Standalone.init(); await Zotero.initComplete(); + // Ingest command line arguments that were not handled due to late command line handler registration. + Zotero.CommandLineIngester.ingest(); }; /** diff --git a/chrome/content/zotero/zotero.mjs b/chrome/content/zotero/zotero.mjs index 44c1cee9cf..43063d9657 100644 --- a/chrome/content/zotero/zotero.mjs +++ b/chrome/content/zotero/zotero.mjs @@ -32,6 +32,7 @@ const Cu = Components.utils; /** XPCOM files to be loaded for all modes **/ const xpcomFilesAll = [ 'zotero', + 'commandLineHandler', 'intl', 'prefs', 'dataDirectory', diff --git a/components/zotero-service.js b/components/zotero-service.js deleted file mode 100644 index eab929797f..0000000000 --- a/components/zotero-service.js +++ /dev/null @@ -1,140 +0,0 @@ -/* - ***** BEGIN LICENSE BLOCK ***** - - Copyright © 2009 Center for History and New Media - George Mason University, Fairfax, Virginia, USA - http://zotero.org - - This file is part of Zotero. - - Zotero is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Zotero is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with Zotero. If not, see . - - - Based on nsChromeExtensionHandler example code by Ed Anuff at - http://kb.mozillazine.org/Dev_:_Extending_the_Chrome_Protocol - - ***** END LICENSE BLOCK ***** -*/ - -/** - * The class representing the Zotero command line handler - */ -function ZoteroCommandLineHandler() {} -ZoteroCommandLineHandler.prototype = { - /* nsICommandLineHandler */ - handle: async function (cmdLine) { - // 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); - if(agent) { - // Don't open a new window - cmdLine.preventDefault = true; - - var command = cmdLine.handleFlagWithParam("ZoteroIntegrationCommand", false); - var docId = cmdLine.handleFlagWithParam("ZoteroIntegrationDocument", false); - var templateVersion = parseInt(cmdLine.handleFlagWithParam("ZoteroIntegrationTemplateVersion", false)); - templateVersion = isNaN(templateVersion) ? 0 : templateVersion; - - zContext.Zotero.Integration.execCommand(agent, command, docId, templateVersion); - } - - var fileToOpen; - // Handle zotero:// and file URIs and prevent them from opening a new window - var param = cmdLine.handleFlagWithParam("url", false); - if (param) { - cmdLine.preventDefault = true; - - var uri = cmdLine.resolveURI(param); - if (uri.schemeIs("zotero")) { - addInitCallback(function (Zotero) { - Zotero.uiReadyPromise - .then(function () { - // Check for existing window and focus it - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - var win = wm.getMostRecentWindow("navigator:browser"); - if (win) { - win.focus(); - win.ZoteroPane.loadURI(uri.spec) - } - }); - }); - } - // See below - else if (uri.schemeIs("file")) { - fileToOpen = OS.Path.fromFileURI(uri.spec) - } - else { - dump(`Not handling URL: ${uri.spec}\n\n`); - } - } - - - // 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. - // Subsequent file openings when closed result in -url with file:// URLs (converted above) - // and don't result in two windows. Here we prevent the double window. - param = fileToOpen; - if (!param) { - param = cmdLine.handleFlagWithParam("file", false); - if (param && isMac()) { - cmdLine.preventDefault = true; - } - } - if (param) { - addInitCallback(function (Zotero) { - // Wait to handle things that require the UI until after it's loaded - Zotero.uiReadyPromise - .then(function () { - var file = Zotero.File.pathToFile(param); - - if(file.leafName.substr(-4).toLowerCase() === ".csl" - || file.leafName.substr(-8).toLowerCase() === ".csl.txt") { - // Install CSL file - Zotero.Styles.install({ file: file.path }, file.path); - } else { - // Ask before importing - var checkState = { - value: Zotero.Prefs.get('import.createNewCollection.fromFileOpenHandler') - }; - if (Services.prompt.confirmCheck(null, Zotero.getString('ingester.importFile.title'), - Zotero.getString('ingester.importFile.text', [file.leafName]), - Zotero.getString('ingester.importFile.intoNewCollection'), - checkState)) { - Zotero.Prefs.set( - 'import.createNewCollection.fromFileOpenHandler', checkState.value - ); - - // Perform file import in front window - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - var browserWindow = wm.getMostRecentWindow("navigator:browser"); - browserWindow.Zotero_File_Interface.importFile({ - file, - createNewCollection: checkState.value - }); - } - } - }); - }); - } - }, - - classID: Components.ID("{531828f8-a16c-46be-b9aa-14845c3b010f}"), - service: true, - _xpcom_categories: [{category:"command-line-handler", entry:"m-zotero"}], - QueryInterface: ChromeUtils.generateQI([Components.interfaces.nsICommandLineHandler]) -}; - -var NSGetFactory = ComponentUtils.generateNSGetFactory([ZoteroService, ZoteroCommandLineHandler]);