commit ae47ae28bdb5801649fde73fed68fc351d6b44e7
parent b073c3e68092edeab61a6afad9819b0f1b4e0ae2
Author: Dan Stillman <dstillman@zotero.org>
Date: Mon, 30 Jan 2017 14:01:04 -0500
Fix #1163, Unable to open zotero urls from tinymce
Diffstat:
5 files changed, 150 insertions(+), 113 deletions(-)
diff --git a/chrome/content/zotero/bindings/styled-textbox.xml b/chrome/content/zotero/bindings/styled-textbox.xml
@@ -440,7 +440,11 @@
this._changed = true;
commandEvent = true;
break;
-
+
+ case 'ZoteroLinkClick':
+ ZoteroPane.loadURI(event.value);
+ break;
+
default:
return;
}
diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js
@@ -51,7 +51,6 @@ var ZoteroPane = new function()
this.getSortedItems = getSortedItems;
this.getSortField = getSortField;
this.getSortDirection = getSortDirection;
- this.loadURI = loadURI;
this.setItemsPaneMessage = setItemsPaneMessage;
this.clearItemsPaneMessage = clearItemsPaneMessage;
this.contextPopupShowing = contextPopupShowing;
@@ -3188,7 +3187,7 @@ var ZoteroPane = new function()
* (e.g. meta-click == new background tab, meta-shift-click == new front tab,
* shift-click == new window, no modifier == frontmost tab
*/
- function loadURI(uris, event) {
+ this.loadURI = function (uris, event) {
if(typeof uris === "string") {
uris = [uris];
}
@@ -3203,9 +3202,22 @@ var ZoteroPane = new function()
if (Zotero.isStandalone) {
if(uri.match(/^https?/)) {
this.launchURL(uri);
- } else {
- Zotero.openInViewer(uri);
+ return;
}
+
+ // Handle no-content zotero: URLs (e.g., zotero://select) without opening viewer
+ if (uri.startsWith('zotero:')) {
+ let nsIURI = Services.io.newURI(uri, null, null);
+ let handler = Components.classes["@mozilla.org/network/protocol;1?name=zotero"]
+ .createInstance(Components.interfaces.nsIProtocolHandler);
+ let extension = handler.wrappedJSObject.getExtension(nsIURI);
+ if (extension.noContent) {
+ extension.doAction(nsIURI);
+ return;
+ }
+ }
+
+ Zotero.openInViewer(uri);
return;
}
diff --git a/components/zotero-protocol-handler.js b/components/zotero-protocol-handler.js
@@ -127,7 +127,7 @@ function ZoteroProtocolHandler() {
router.add('groups/:groupID/:scopeObject/:scopeObjectKey/items');
// All items
- router.add('library/items', function () {
+ router.add('library/items/:objectKey', function () {
params.libraryID = userLibraryID;
});
router.add('groups/:groupID/items');
@@ -796,73 +796,70 @@ function ZoteroProtocolHandler() {
* zotero://select/[type]/1234 (not consistent across synced machines)
*/
var SelectExtension = {
- newChannel: function (uri) {
- return new AsyncChannel(uri, function* () {
- var userLibraryID = Zotero.Libraries.userLibraryID;
-
- var path = uri.path;
- if (!path) {
- return 'Invalid URL';
- }
- // Strip leading '/'
- path = path.substr(1);
- var mimeType, content = '';
-
- var params = {
- objectType: 'item'
- };
- var router = new Zotero.Router(params);
-
- // Item within a collection or search
- router.add('library/:scopeObject/:scopeObjectKey/items/:objectKey', function () {
- params.libraryID = userLibraryID;
- });
- router.add('groups/:groupID/:scopeObject/:scopeObjectKey/items/:objectKey');
-
- // All items
- router.add('library/items/:objectKey', function () {
- params.libraryID = userLibraryID;
- });
- router.add('groups/:groupID/items/:objectKey');
-
- // Old-style URLs
- router.add('item/:id', function () {
- var lkh = Zotero.Items.parseLibraryKeyHash(params.id);
- if (lkh) {
- params.libraryID = lkh.libraryID;
- params.objectKey = lkh.key;
- }
- else {
- params.objectID = params.id;
- }
- delete params.id;
- });
- router.run(path);
-
- try {
- Zotero.API.parseParams(params);
- var results = yield Zotero.API.getResultsFromParams(params);
- }
- catch (e) {
- Zotero.debug(e, 1);
- return e.toString();
+ noContent: true,
+
+ doAction: Zotero.Promise.coroutine(function* (uri) {
+ var userLibraryID = Zotero.Libraries.userLibraryID;
+
+ var path = uri.path;
+ if (!path) {
+ return 'Invalid URL';
+ }
+ // Strip leading '/'
+ path = path.substr(1);
+ var mimeType, content = '';
+
+ var params = {
+ objectType: 'item'
+ };
+ var router = new Zotero.Router(params);
+
+ // Item within a collection or search
+ router.add('library/:scopeObject/:scopeObjectKey/items/:objectKey', function () {
+ params.libraryID = userLibraryID;
+ });
+ router.add('groups/:groupID/:scopeObject/:scopeObjectKey/items/:objectKey');
+
+ // All items
+ router.add('library/items/:objectKey', function () {
+ params.libraryID = userLibraryID;
+ });
+ router.add('groups/:groupID/items/:objectKey');
+
+ // Old-style URLs
+ router.add('item/:id', function () {
+ var lkh = Zotero.Items.parseLibraryKeyHash(params.id);
+ if (lkh) {
+ params.libraryID = lkh.libraryID;
+ params.objectKey = lkh.key;
}
-
-
- if (!results.length) {
- var msg = "Selected items not found";
- Zotero.debug(msg, 2);
- Components.utils.reportError(msg);
- return;
+ else {
+ params.objectID = params.id;
}
-
- var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Components.interfaces.nsIWindowMediator);
- var win = wm.getMostRecentWindow("navigator:browser");
-
- // TODO: Currently only able to select one item
- yield win.ZoteroPane.selectItem(results[0].id);
+ delete params.id;
});
+ router.run(path);
+
+ Zotero.API.parseParams(params);
+ var results = yield Zotero.API.getResultsFromParams(params);
+
+ if (!results.length) {
+ var msg = "Items not found";
+ Zotero.debug(msg, 2);
+ Components.utils.reportError(msg);
+ return;
+ }
+
+ var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Components.interfaces.nsIWindowMediator);
+ var win = wm.getMostRecentWindow("navigator:browser");
+
+ // TODO: Currently only able to select one item
+ return win.ZoteroPane.selectItem(results[0].id);
+ }),
+
+ newChannel: function (uri) {
+ this.doAction(uri);
}
};
@@ -1039,6 +1036,22 @@ ZoteroProtocolHandler.prototype = {
return false;
},
+ getExtension: function (uri) {
+ let uriString = uri;
+ if (uri instanceof Components.interfaces.nsIURI) {
+ uriString = uri.spec;
+ }
+ uriString = uriString.toLowerCase();
+
+ for (let extSpec in this._extensions) {
+ if (uriString.startsWith(extSpec)) {
+ return this._extensions[extSpec];
+ }
+ }
+
+ return false;
+ },
+
newURI : function(spec, charset, baseURI) {
var newURL = Components.classes["@mozilla.org/network/standard-url;1"]
.createInstance(Components.interfaces.nsIStandardURL);
@@ -1056,53 +1069,49 @@ ZoteroProtocolHandler.prototype = {
var newChannel = null;
try {
- var uriString = uri.spec.toLowerCase();
+ let ext = this.getExtension(uri);
- for (var extSpec in this._extensions) {
- var ext = this._extensions[extSpec];
-
- if (uriString.indexOf(extSpec) == 0) {
- if (!this._principal) {
- if (ext.loadAsChrome) {
- var chromeURI = chromeService.newURI(DUMMY_CHROME_URL, null, null);
- var chromeChannel = chromeService.newChannel(chromeURI);
-
- // Cache System Principal from chrome request
- // so proxied pages load with chrome privileges
- this._principal = chromeChannel.owner;
-
- var chromeRequest = chromeChannel.QueryInterface(Components.interfaces.nsIRequest);
- chromeRequest.cancel(0x804b0002); // BINDING_ABORTED
- }
- }
-
- var extChannel = ext.newChannel(uri);
- // Extension returned null, so cancel request
- if (!extChannel) {
- var chromeURI = chromeService.newURI(DUMMY_CHROME_URL, null, null);
- var extChannel = chromeService.newChannel(chromeURI);
- var chromeRequest = extChannel.QueryInterface(Components.interfaces.nsIRequest);
- chromeRequest.cancel(0x804b0002); // BINDING_ABORTED
- }
-
- // Apply cached principal to extension channel
- if (this._principal) {
- extChannel.owner = this._principal;
- }
+ if (!ext) {
+ // Return cancelled channel for unknown paths
+ //
+ // These can be in the form zotero://example.com/... -- maybe for "//example.com" URLs?
+ var chromeURI = chromeService.newURI(DUMMY_CHROME_URL, null, null);
+ var extChannel = chromeService.newChannel(chromeURI);
+ var chromeRequest = extChannel.QueryInterface(Components.interfaces.nsIRequest);
+ chromeRequest.cancel(0x804b0002); // BINDING_ABORTED
+ return extChannel;
+ }
+
+ if (!this._principal) {
+ if (ext.loadAsChrome) {
+ var chromeURI = chromeService.newURI(DUMMY_CHROME_URL, null, null);
+ var chromeChannel = chromeService.newChannel(chromeURI);
- if(!extChannel.originalURI) extChannel.originalURI = uri;
+ // Cache System Principal from chrome request
+ // so proxied pages load with chrome privileges
+ this._principal = chromeChannel.owner;
- return extChannel;
+ var chromeRequest = chromeChannel.QueryInterface(Components.interfaces.nsIRequest);
+ chromeRequest.cancel(0x804b0002); // BINDING_ABORTED
}
}
- // Return cancelled channel for unknown paths
- //
- // These can be in the form zotero://example.com/... -- maybe for "//example.com" URLs?
- var chromeURI = chromeService.newURI(DUMMY_CHROME_URL, null, null);
- var extChannel = chromeService.newChannel(chromeURI);
- var chromeRequest = extChannel.QueryInterface(Components.interfaces.nsIRequest);
- chromeRequest.cancel(0x804b0002); // BINDING_ABORTED
+ var extChannel = ext.newChannel(uri);
+ // Extension returned null, so cancel request
+ if (!extChannel) {
+ var chromeURI = chromeService.newURI(DUMMY_CHROME_URL, null, null);
+ var extChannel = chromeService.newChannel(chromeURI);
+ var chromeRequest = extChannel.QueryInterface(Components.interfaces.nsIRequest);
+ chromeRequest.cancel(0x804b0002); // BINDING_ABORTED
+ }
+
+ // Apply cached principal to extension channel
+ if (this._principal) {
+ extChannel.owner = this._principal;
+ }
+
+ if(!extChannel.originalURI) extChannel.originalURI = uri;
+
return extChannel;
}
catch (e) {
diff --git a/resource/tinymce/note.html b/resource/tinymce/note.html
@@ -57,6 +57,15 @@
zoteroExecCommand(ed.getDoc(), cmd, ui, value);
});
});
+
+ ["ZoteroLinkClick"].forEach(function (command) {
+ ed.addCommand(command, function (ui, value) {
+ zoteroHandleEvent({
+ type: command,
+ value
+ });
+ });
+ });
},
// More restrictive version of default set, with JS/etc. removed
diff --git a/resource/tinymce/plugins/link/plugin.js b/resource/tinymce/plugins/link/plugin.js
@@ -59,11 +59,14 @@ tinymce.PluginManager.add('link', function(editor) {
}
function openDetachedWindow(url) {
+ // Added by Zotero
+ editor.execCommand('ZoteroLinkClick', false, url);
+
// Chrome and Webkit has implemented noopener and works correctly with/without popup blocker
// Firefox has it implemented noopener but when the popup blocker is activated it doesn't work
// Edge has only implemented noreferrer and it seems to remove opener as well
// Older IE versions pre IE 11 falls back to a window.open approach
- if (!tinymce.Env.ie || tinymce.Env.ie > 10) {
+ /*if (!tinymce.Env.ie || tinymce.Env.ie > 10) {
var link = document.createElement('a');
link.target = '_blank';
link.href = url;
@@ -81,7 +84,7 @@ tinymce.PluginManager.add('link', function(editor) {
doc.write('<meta http-equiv="refresh" content="0; url=' + tinymce.DOM.encode(url) + '">');
doc.close();
}
- }
+ }*/
}
function gotoLink(a) {