diff --git a/chrome/content/zotero/xpcom/connector/cachedTypes.js b/chrome/content/zotero/xpcom/connector/cachedTypes.js index 369e8d863c..7cc1c12419 100644 --- a/chrome/content/zotero/xpcom/connector/cachedTypes.js +++ b/chrome/content/zotero/xpcom/connector/cachedTypes.js @@ -84,7 +84,7 @@ Zotero.Connector_Types = new function() { return ZOTERO_CONFIG.BOOKMARKLET_URL+"images/"+icon; } else if(Zotero.isFx) { return "chrome://zotero/skin/"+icon; - } else if(Zotero.isChrome) { + } else if(Zotero.isBrowserExt) { return chrome.extension.getURL("images/"+icon); } else if(Zotero.isSafari) { return safari.extension.baseURI+"images/"+icon; diff --git a/chrome/content/zotero/xpcom/connector/connector.js b/chrome/content/zotero/xpcom/connector/connector.js index d412047ab9..db68d7771f 100644 --- a/chrome/content/zotero/xpcom/connector/connector.js +++ b/chrome/content/zotero/xpcom/connector/connector.js @@ -240,7 +240,7 @@ Zotero.Connector = new function() { this.callMethod("saveItems", data, callback, tab); return; - } else if(Zotero.isChrome && !Zotero.isBookmarklet) { + } else if(Zotero.isBrowserExt && !Zotero.isBookmarklet) { var self = this; chrome.cookies.getAll({url: tab.url}, function(cookies) { var cookieHeader = ''; diff --git a/chrome/content/zotero/xpcom/connector/translate_item.js b/chrome/content/zotero/xpcom/connector/translate_item.js index 490c918d61..d095db85d1 100644 --- a/chrome/content/zotero/xpcom/connector/translate_item.js +++ b/chrome/content/zotero/xpcom/connector/translate_item.js @@ -544,7 +544,7 @@ Zotero.Translate.ItemSaver.prototype = { } attachment.md5 = hash; - if(Zotero.isChrome && !Zotero.isBookmarklet) { + if(Zotero.isBrowserExt && !Zotero.isBookmarklet) { // In Chrome, we don't use messaging for Zotero.API.uploadAttachment, since // we can't pass ArrayBuffers to the background page Zotero.API.uploadAttachment(attachment, attachmentCallback.bind(this, attachment)); diff --git a/chrome/content/zotero/xpcom/connector/translator.js b/chrome/content/zotero/xpcom/connector/translator.js index 603af97b66..d919313853 100644 --- a/chrome/content/zotero/xpcom/connector/translator.js +++ b/chrome/content/zotero/xpcom/connector/translator.js @@ -42,7 +42,7 @@ Zotero.Translators = new function() { this.init = function(translators) { if(!translators) { translators = []; - if((Zotero.isChrome || Zotero.isSafari) && localStorage["translatorMetadata"]) { + if((Zotero.isBrowserExt || Zotero.isSafari) && localStorage["translatorMetadata"]) { try { translators = JSON.parse(localStorage["translatorMetadata"]); if(typeof translators !== "object") { @@ -196,7 +196,7 @@ Zotero.Translators = new function() { if(j === 0) { converterFunctions.push(null); - } else if(Zotero.isChrome || Zotero.isSafari) { + } else if(Zotero.isBrowserExt || Zotero.isSafari) { // in Chrome/Safari, the converterFunction needs to be passed as JSON, so // just push an array with the proper and proxyHosts converterFunctions.push([properHosts[j-1], proxyHosts[j-1]]); @@ -303,7 +303,7 @@ Zotero.Translators = new function() { } // Store - if(Zotero.isChrome || Zotero.isSafari) { + if (Zotero.isBrowserExt || Zotero.isSafari) { var serialized = JSON.stringify(serializedTranslators); localStorage["translatorMetadata"] = serialized; Zotero.debug("Translators: Saved updated translator list ("+serialized.length+" characters)"); @@ -374,7 +374,8 @@ Zotero.Translators.CodeGetter.prototype.getCodeFor = function(i) { const TRANSLATOR_REQUIRED_PROPERTIES = ["translatorID", "translatorType", "label", "creator", "target", "priority", "lastUpdated"]; -var TRANSLATOR_PASSING_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES.concat(["browserSupport", "code", "runMode"]); +var TRANSLATOR_PASSING_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES + .concat(["browserSupport", "code", "runMode", "itemType"]); var TRANSLATOR_SAVE_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES.concat(["browserSupport"]); /** * @class Represents an individual translator diff --git a/chrome/content/zotero/xpcom/translation/translate.js b/chrome/content/zotero/xpcom/translation/translate.js index 7f5d00201f..e93d0dd22b 100644 --- a/chrome/content/zotero/xpcom/translation/translate.js +++ b/chrome/content/zotero/xpcom/translation/translate.js @@ -373,7 +373,12 @@ Zotero.Translate.Sandbox = { var translator = translation.translator[0]; translator = typeof translator === "object" ? translator : Zotero.Translators.get(translator); - translation._loadTranslator(translator) + // Zotero.Translators.get returns a value in the client and a promise in connectors + // so we normalize the value to a promise here + Zotero.Promise.resolve(translator) + .then(function(translator) { + return translation._loadTranslator(translator) + }) .then(function() { if(Zotero.isFx && !Zotero.isBookmarklet) { // do same origin check @@ -400,7 +405,7 @@ Zotero.Translate.Sandbox = { }) .then(function () { setDefaultHandlers(translate, translation); - sandbox = translation._sandboxManager.sandbox; + var sandbox = translation._sandboxManager.sandbox; if(!Zotero.Utilities.isEmpty(sandbox.exports)) { sandbox.exports.Zotero = sandbox.Zotero; sandbox = sandbox.exports; @@ -679,7 +684,7 @@ Zotero.Translate.Sandbox = { // refuse to save very long tags if(item.tags) { for(var i=0; i 255) { @@ -1111,7 +1116,9 @@ Zotero.Translate.Base.prototype = { // if detection returns immediately, return found translators var me = this; - return potentialTranslators.spread(function(allPotentialTranslators, properToProxyFunctions) { + return potentialTranslators.then(function(result) { + var allPotentialTranslators = result[0]; + var properToProxyFunctions = result[1]; me._potentialTranslators = []; me._foundTranslators = []; @@ -1266,25 +1273,35 @@ Zotero.Translate.Base.prototype = { /** * Called when translator has been retrieved and loaded */ - "_translateTranslatorLoaded": Zotero.Promise.coroutine(function* () { + "_translateTranslatorLoaded": Zotero.Promise.method(function() { // set display options to default if they don't exist if(!this._displayOptions) this._displayOptions = this._translatorInfo.displayOptions || {}; - yield this._prepareTranslation(); - - Zotero.debug("Translate: Beginning translation with "+this.translator[0].label); - - this.incrementAsyncProcesses("Zotero.Translate#translate()"); - - // translate - try { - Function.prototype.apply.call(this._sandboxManager.sandbox["do"+this._entryFunctionSuffix], null, this._getParameters()); - } catch(e) { - this.complete(false, e); - return false; + var loadPromise = this._prepareTranslation(); + if (this.noWait) { + if (!loadPromise.isResolved()) { + throw new Error("Load promise is not resolved in noWait mode"); + } + rest.apply(this, arguments); + } else { + return loadPromise.then(() => rest.apply(this, arguments)) } - this.decrementAsyncProcesses("Zotero.Translate#translate()"); + function rest() { + Zotero.debug("Translate: Beginning translation with " + this.translator[0].label); + + this.incrementAsyncProcesses("Zotero.Translate#translate()"); + + // translate + try { + Function.prototype.apply.call(this._sandboxManager.sandbox["do" + this._entryFunctionSuffix], null, this._getParameters()); + } catch (e) { + this.complete(false, e); + return false; + } + + this.decrementAsyncProcesses("Zotero.Translate#translate()"); + } }), /** @@ -1596,13 +1613,12 @@ Zotero.Translate.Base.prototype = { let lab = this._potentialTranslators[0].label; this._loadTranslator(this._potentialTranslators[0]) - .bind(this) .then(function() { return this._detectTranslatorLoaded(); - }) + }.bind(this)) .catch(function (e) { this.complete(false, e); - }); + }.bind(this)); }, /** @@ -2309,7 +2325,7 @@ Zotero.Translate.Export.prototype.getTranslators = function() { /** * Does the actual export, after code has been loaded and parsed */ -Zotero.Translate.Export.prototype._prepareTranslation = Zotero.Promise.coroutine(function* () { +Zotero.Translate.Export.prototype._prepareTranslation = Zotero.Promise.method(function () { this._progress = undefined; // initialize ItemGetter @@ -2320,6 +2336,7 @@ Zotero.Translate.Export.prototype._prepareTranslation = Zotero.Promise.coroutine var configOptions = this._translatorInfo.configOptions || {}, getCollections = configOptions.getCollections || false; + var loadPromise = Zotero.Promise.resolve(); switch (this._export.type) { case 'collection': this._itemGetter.setCollection(this._export.collection, getCollections); @@ -2328,7 +2345,7 @@ Zotero.Translate.Export.prototype._prepareTranslation = Zotero.Promise.coroutine this._itemGetter.setItems(this._export.items); break; case 'library': - yield this._itemGetter.setAll(this._export.id, getCollections); + loadPromise = this._itemGetter.setAll(this._export.id, getCollections); break; default: throw new Error('No export set up'); @@ -2336,27 +2353,38 @@ Zotero.Translate.Export.prototype._prepareTranslation = Zotero.Promise.coroutine } delete this._export; - // export file data, if requested - if(this._displayOptions["exportFileData"]) { - this.location = this._itemGetter.exportFiles(this.location, this.translator[0].target); - } - - // initialize IO - // this is currently hackish since we pass null callbacks to the init function (they have - // callbacks to be consistent with import, but they are synchronous, so we ignore them) - if(!this.location) { - this._io = new Zotero.Translate.IO.String(null, this.path ? this.path : "", this._sandboxManager); - this._io.init(configOptions["dataMode"], function() {}); - } else if(!Zotero.Translate.IO.Write) { - throw new Error("Writing to files is not supported in this build of Zotero."); + if (this.noWait) { + if (!loadPromise.isResolved()) { + throw new Error("Load promise is not resolved in noWait mode"); + } + rest.apply(this, arguments); } else { - this._io = new Zotero.Translate.IO.Write(this.location); - this._io.init(configOptions["dataMode"], - this._displayOptions["exportCharset"] ? this._displayOptions["exportCharset"] : null, - function() {}); + return loadPromise.then(() => rest.apply(this, arguments)) } - this._sandboxManager.importObject(this._io); + function rest() { + // export file data, if requested + if(this._displayOptions["exportFileData"]) { + this.location = this._itemGetter.exportFiles(this.location, this.translator[0].target); + } + + // initialize IO + // this is currently hackish since we pass null callbacks to the init function (they have + // callbacks to be consistent with import, but they are synchronous, so we ignore them) + if(!this.location) { + this._io = new Zotero.Translate.IO.String(null, this.path ? this.path : "", this._sandboxManager); + this._io.init(configOptions["dataMode"], function() {}); + } else if(!Zotero.Translate.IO.Write) { + throw new Error("Writing to files is not supported in this build of Zotero."); + } else { + this._io = new Zotero.Translate.IO.Write(this.location); + this._io.init(configOptions["dataMode"], + this._displayOptions["exportCharset"] ? this._displayOptions["exportCharset"] : null, + function() {}); + } + + this._sandboxManager.importObject(this._io); + } }); /** diff --git a/chrome/content/zotero/xpcom/translation/translator.js b/chrome/content/zotero/xpcom/translation/translator.js index ab98c32d95..64b76fd951 100644 --- a/chrome/content/zotero/xpcom/translation/translator.js +++ b/chrome/content/zotero/xpcom/translation/translator.js @@ -29,10 +29,10 @@ var TRANSLATOR_REQUIRED_PROPERTIES = ["translatorID", "translatorType", "label", // Properties that are preserved if present var TRANSLATOR_OPTIONAL_PROPERTIES = ["browserSupport", "minVersion", "maxVersion", "inRepository", "configOptions", "displayOptions", - "hiddenPrefs"]; + "hiddenPrefs", "itemType"]; // Properties that are passed from background to inject page in connector var TRANSLATOR_PASSING_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES. - concat(["browserSupport", "code", "runMode"]); + concat(["browserSupport", "code", "runMode", "itemType"]); // Properties that are saved in connector if set but not required var TRANSLATOR_SAVE_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES.concat(["browserSupport"]);