Fix #1163, Unable to open zotero urls from tinymce

This commit is contained in:
Dan Stillman 2017-01-30 14:01:04 -05:00
parent b073c3e680
commit ae47ae28bd
5 changed files with 152 additions and 115 deletions

View File

@ -440,7 +440,11 @@
this._changed = true; this._changed = true;
commandEvent = true; commandEvent = true;
break; break;
case 'ZoteroLinkClick':
ZoteroPane.loadURI(event.value);
break;
default: default:
return; return;
} }

View File

@ -51,7 +51,6 @@ var ZoteroPane = new function()
this.getSortedItems = getSortedItems; this.getSortedItems = getSortedItems;
this.getSortField = getSortField; this.getSortField = getSortField;
this.getSortDirection = getSortDirection; this.getSortDirection = getSortDirection;
this.loadURI = loadURI;
this.setItemsPaneMessage = setItemsPaneMessage; this.setItemsPaneMessage = setItemsPaneMessage;
this.clearItemsPaneMessage = clearItemsPaneMessage; this.clearItemsPaneMessage = clearItemsPaneMessage;
this.contextPopupShowing = contextPopupShowing; this.contextPopupShowing = contextPopupShowing;
@ -3188,7 +3187,7 @@ var ZoteroPane = new function()
* (e.g. meta-click == new background tab, meta-shift-click == new front tab, * (e.g. meta-click == new background tab, meta-shift-click == new front tab,
* shift-click == new window, no modifier == frontmost tab * shift-click == new window, no modifier == frontmost tab
*/ */
function loadURI(uris, event) { this.loadURI = function (uris, event) {
if(typeof uris === "string") { if(typeof uris === "string") {
uris = [uris]; uris = [uris];
} }
@ -3203,9 +3202,22 @@ var ZoteroPane = new function()
if (Zotero.isStandalone) { if (Zotero.isStandalone) {
if(uri.match(/^https?/)) { if(uri.match(/^https?/)) {
this.launchURL(uri); this.launchURL(uri);
} else { return;
Zotero.openInViewer(uri);
} }
// 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; return;
} }

View File

@ -127,7 +127,7 @@ function ZoteroProtocolHandler() {
router.add('groups/:groupID/:scopeObject/:scopeObjectKey/items'); router.add('groups/:groupID/:scopeObject/:scopeObjectKey/items');
// All items // All items
router.add('library/items', function () { router.add('library/items/:objectKey', function () {
params.libraryID = userLibraryID; params.libraryID = userLibraryID;
}); });
router.add('groups/:groupID/items'); router.add('groups/:groupID/items');
@ -796,73 +796,70 @@ function ZoteroProtocolHandler() {
* zotero://select/[type]/1234 (not consistent across synced machines) * zotero://select/[type]/1234 (not consistent across synced machines)
*/ */
var SelectExtension = { var SelectExtension = {
newChannel: function (uri) { noContent: true,
return new AsyncChannel(uri, function* () {
var userLibraryID = Zotero.Libraries.userLibraryID; doAction: Zotero.Promise.coroutine(function* (uri) {
var userLibraryID = Zotero.Libraries.userLibraryID;
var path = uri.path;
if (!path) { var path = uri.path;
return 'Invalid URL'; if (!path) {
} return 'Invalid URL';
// Strip leading '/' }
path = path.substr(1); // Strip leading '/'
var mimeType, content = ''; path = path.substr(1);
var mimeType, content = '';
var params = {
objectType: 'item' var params = {
}; objectType: 'item'
var router = new Zotero.Router(params); };
var router = new Zotero.Router(params);
// Item within a collection or search
router.add('library/:scopeObject/:scopeObjectKey/items/:objectKey', function () { // Item within a collection or search
params.libraryID = userLibraryID; 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();
}
if (!results.length) {
var msg = "Selected 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
yield win.ZoteroPane.selectItem(results[0].id);
}); });
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);
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; 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) { newURI : function(spec, charset, baseURI) {
var newURL = Components.classes["@mozilla.org/network/standard-url;1"] var newURL = Components.classes["@mozilla.org/network/standard-url;1"]
.createInstance(Components.interfaces.nsIStandardURL); .createInstance(Components.interfaces.nsIStandardURL);
@ -1056,53 +1069,49 @@ ZoteroProtocolHandler.prototype = {
var newChannel = null; var newChannel = null;
try { try {
var uriString = uri.spec.toLowerCase(); let ext = this.getExtension(uri);
for (var extSpec in this._extensions) { if (!ext) {
var ext = this._extensions[extSpec]; // Return cancelled channel for unknown paths
//
if (uriString.indexOf(extSpec) == 0) { // These can be in the form zotero://example.com/... -- maybe for "//example.com" URLs?
if (!this._principal) { var chromeURI = chromeService.newURI(DUMMY_CHROME_URL, null, null);
if (ext.loadAsChrome) { var extChannel = chromeService.newChannel(chromeURI);
var chromeURI = chromeService.newURI(DUMMY_CHROME_URL, null, null); var chromeRequest = extChannel.QueryInterface(Components.interfaces.nsIRequest);
var chromeChannel = chromeService.newChannel(chromeURI); chromeRequest.cancel(0x804b0002); // BINDING_ABORTED
return extChannel;
// Cache System Principal from chrome request }
// so proxied pages load with chrome privileges
this._principal = chromeChannel.owner; if (!this._principal) {
if (ext.loadAsChrome) {
var chromeRequest = chromeChannel.QueryInterface(Components.interfaces.nsIRequest); var chromeURI = chromeService.newURI(DUMMY_CHROME_URL, null, null);
chromeRequest.cancel(0x804b0002); // BINDING_ABORTED var chromeChannel = chromeService.newChannel(chromeURI);
}
}
var extChannel = ext.newChannel(uri); // Cache System Principal from chrome request
// Extension returned null, so cancel request // so proxied pages load with chrome privileges
if (!extChannel) { this._principal = chromeChannel.owner;
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 var chromeRequest = chromeChannel.QueryInterface(Components.interfaces.nsIRequest);
if (this._principal) { chromeRequest.cancel(0x804b0002); // BINDING_ABORTED
extChannel.owner = this._principal;
}
if(!extChannel.originalURI) extChannel.originalURI = uri;
return extChannel;
} }
} }
// Return cancelled channel for unknown paths var extChannel = ext.newChannel(uri);
// // Extension returned null, so cancel request
// These can be in the form zotero://example.com/... -- maybe for "//example.com" URLs? if (!extChannel) {
var chromeURI = chromeService.newURI(DUMMY_CHROME_URL, null, null); var chromeURI = chromeService.newURI(DUMMY_CHROME_URL, null, null);
var extChannel = chromeService.newChannel(chromeURI); var extChannel = chromeService.newChannel(chromeURI);
var chromeRequest = extChannel.QueryInterface(Components.interfaces.nsIRequest); var chromeRequest = extChannel.QueryInterface(Components.interfaces.nsIRequest);
chromeRequest.cancel(0x804b0002); // BINDING_ABORTED 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; return extChannel;
} }
catch (e) { catch (e) {

View File

@ -57,6 +57,15 @@
zoteroExecCommand(ed.getDoc(), cmd, ui, value); 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 // More restrictive version of default set, with JS/etc. removed

View File

@ -59,11 +59,14 @@ tinymce.PluginManager.add('link', function(editor) {
} }
function openDetachedWindow(url) { function openDetachedWindow(url) {
// Added by Zotero
editor.execCommand('ZoteroLinkClick', false, url);
// Chrome and Webkit has implemented noopener and works correctly with/without popup blocker // 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 // 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 // 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 // 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'); var link = document.createElement('a');
link.target = '_blank'; link.target = '_blank';
link.href = url; 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.write('<meta http-equiv="refresh" content="0; url=' + tinymce.DOM.encode(url) + '">');
doc.close(); doc.close();
} }
} }*/
} }
function gotoLink(a) { function gotoLink(a) {