|
| 1 | +# Zotero Connectors |
| 2 | + |
| 3 | +[](https://travis-ci.org/zotero/zotero-connectors) |
| 4 | + |
| 5 | +## Building |
| 6 | + |
| 7 | +1. `git clone --recursive https://github.com/zotero/zotero-connectors.git` |
| 8 | +1. `cd zotero-connectors` |
| 9 | +1. `npm install` |
| 10 | +1. `./build.sh -d` |
| 11 | + |
| 12 | +The connectors are built in `build/`. |
| 13 | + |
| 14 | +## Running from the build directory |
| 15 | + |
| 16 | +### Chrome |
| 17 | + |
| 18 | +1. Go to chrome://extensions/ |
| 19 | +1. Enable "Developer Mode". |
| 20 | +1. Click "Load unpacked extension…" and select the `build/browserExt` directory. |
| 21 | + |
| 22 | +### Firefox |
| 23 | + |
| 24 | +1. Go to about:debugging |
| 25 | +1. Click "Load Temporary Add-on" and select the `build/browserExt/manifest.json` file. |
| 26 | + |
| 27 | +### Safari |
| 28 | + |
| 29 | +See https://github.com/zotero/safari-app-extension |
| 30 | + |
| 31 | +## Automatic rebuilding |
| 32 | + |
| 33 | +1. `cd` to project root |
| 34 | +1. `npm install` |
| 35 | +1. `build.sh -d` |
| 36 | +1. `gulp watch` |
| 37 | + |
| 38 | +As files are changed, the connectors will be rebuilt automatically. You will need to manually reload the extension |
| 39 | +in the browser being developed for. |
| 40 | + |
| 41 | +## Requirements for packaging extensions from the command line |
| 42 | + |
| 43 | +* Copy `config.sh-sample` to `config.sh` and modify as necessary |
| 44 | + |
| 45 | +# Developing |
| 46 | + |
| 47 | +An overview of the Zotero Connector architecture. |
| 48 | + |
| 49 | +## Technologies |
| 50 | + |
| 51 | +##### Chrome/Firefox Browser Extension Framework |
| 52 | + |
| 53 | +The extension uses the WebExtension API cross-browser technology. See [Chrome Extension docs](https://developer.chrome.com/extensions) |
| 54 | +and [Firefox Extension docs](https://developer.mozilla.org/en-US/Add-ons/WebExtensions) for more information. |
| 55 | + |
| 56 | +##### Safari Extension Framework |
| 57 | + |
| 58 | +For Safari specifics see https://github.com/zotero/safari-app-extension |
| 59 | + |
| 60 | +##### Zotero Translator Framework |
| 61 | + |
| 62 | +The Connectors use the [Zotero translate architecture](https://github.com/zotero/translate), to support page translation. |
| 63 | +A basic understanding of how translation works is highly useful in understanding the codebase. |
| 64 | + |
| 65 | +## Components |
| 66 | + |
| 67 | +Saving resources to Zotero library is facilitated by two major components: the Zotero Connector running in the browser |
| 68 | +and either the Zotero client or zotero.org web api. The Zotero Connector itself is split into two components: |
| 69 | +code running on the webpage and a background process. |
| 70 | + |
| 71 | +<img src="http://i.imgur.com/4r2qRqe.png" width="600"/> |
| 72 | + |
| 73 | + |
| 74 | +##### a) Injected scripts for individual webpages |
| 75 | + |
| 76 | +Each webpage is injected ([Chrome](https://developer.chrome.com/extensions/content_scripts)/[Firefox](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts)/[Safari](https://developer.apple.com/documentation/safariservices/injecting-a-script-into-a-webpage)) |
| 77 | +with a full Zotero [translation framework](https://github.com/zotero/zotero-connectors/blob/e1a16c8ad2e17c6893554c3f376384e18182202d/gulpfile.js#L45-L79). |
| 78 | +A [*Zotero.Translate.Web*](https://github.com/zotero/zotero-connectors/blob/e1a16c8ad2e17c6893554c3f376384e18182202d/src/common/inject/inject.jsx#L314-L314) |
| 79 | +instance orchestrates running individual translators for detection and translation. |
| 80 | + |
| 81 | +The translation framework provides custom classes concerning |
| 82 | +[translator retrieval](https://github.com/zotero/zotero-connectors/blob/e1a16c8ad2e17c6893554c3f376384e18182202d/src/common/translators.js) |
| 83 | +and [item saving](https://github.com/zotero/zotero-connectors/blob/e1a16c8ad2e17c6893554c3f376384e18182202d/src/common/translate_item.js). |
| 84 | +These custom classes talk to the background process (b) of the Zotero Connector for functionality outside the translation |
| 85 | +framework, such as retrieving translator code and sending translated items either to Zotero (c) or zotero.org (d). |
| 86 | + |
| 87 | +##### b) Background process |
| 88 | + |
| 89 | +The Connector runs a [background process](https://github.com/zotero/zotero-connectors/blob/e1a16c8ad2e17c6893554c3f376384e18182202d/gulpfile.js#L95-L125) |
| 90 | +([Chrome](https://developer.chrome.com/extensions/event_pages)/[Firefox](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts)/[Safari](https://developer.apple.com/documentation/safariservices/building-a-safari-app-extension)) |
| 91 | +which works as a middle-layer between the translation framework running in inject scripts (a) and Zotero (c) or zotero.org (d). |
| 92 | + |
| 93 | +The background process maintains a cache of translators and performs the initial [translator detection using URL matching](https://github.com/zotero/zotero-connectors/blob/e1a16c8ad2e17c6893554c3f376384e18182202d/src/common/translators.js#L140-L196). |
| 94 | +Translators whose target regexp matches the URL of a given webpage are then further tested by running `detectWeb()` |
| 95 | +in injected scripts. A list of translators and their code is |
| 96 | +fetched either from [Zotero (c) or zotero.org (d)](https://github.com/zotero/zotero-connectors/blob/e1a16c8ad2e17c6893554c3f376384e18182202d/src/common/repo.js#L140-L155). |
| 97 | + |
| 98 | +The background process is also responsible for updating the extension UI, kicking off translations, storing and |
| 99 | +retrieving connector preferences and sending translated items to Zotero or zotero.org. Browser specific scripts are |
| 100 | +available for [BrowserExt](https://github.com/zotero/zotero-connectors/blob/master/src/browserExt/background.js) |
| 101 | +and [Safari](https://github.com/zotero/zotero-connectors/blob/master/src/safari/global.html). |
| 102 | + |
| 103 | +##### c) Connector server in Zotero |
| 104 | + |
| 105 | +When Zotero is open it runs a [connector HTTP server](https://www.zotero.org/support/dev/client_coding/connector_http_server) |
| 106 | +on port 23119. The HTTP server API accommodates interactions between the Connectors and Zotero client. Calls to |
| 107 | +[*Zotero.Connector.callMethod(endpoint)*](https://github.com/zotero/zotero-connectors/blob/e1a16c8ad2e17c6893554c3f376384e18182202d/src/common/connector.js#L150) |
| 108 | +in this codebase are translated to HTTP requests to the connector server. |
| 109 | + |
| 110 | +Note that Zotero cannot interact with the connectors on its own accord. All communication is Connector initiated. |
| 111 | + |
| 112 | +##### d) zotero.org API |
| 113 | + |
| 114 | +When Zotero is not available item saving falls back to |
| 115 | +using [zotero.org API](https://www.zotero.org/support/dev/web_api/v3/start). |
| 116 | +The interactions with zotero.org API are defined in [api.js](https://github.com/zotero/zotero-connectors/blob/e1a16c8ad2e17c6893554c3f376384e18182202d/src/common/api.js) |
| 117 | + |
| 118 | +## Message passing |
| 119 | + |
| 120 | +The only way for the background extension process and injected scripts to communicate is using the message passing |
| 121 | +protocol provided by the browsers ([Chrome](https://developer.chrome.com/extensions/messaging)/[Firefox](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts#Communicating_with_background_scripts)/[Safari](https://developer.apple.com/documentation/safariservices/passing-messages-between-safari-app-extensions-and-injected-scripts)). |
| 122 | +Injected scripts often need to communicate to background scripts. To simplify |
| 123 | +these interactions, calls to functions in background scripts are monkey-patched in injected scripts. These calls are |
| 124 | +asynchronous and if a return value is required, it is provided either to a callback function as the last argument of |
| 125 | +the call or as a resolving value of a promise returned. |
| 126 | + |
| 127 | +[*messages.js*](https://github.com/zotero/zotero-connectors/blob/e1a16c8ad2e17c6893554c3f376384e18182202d/src/common/messages.js) |
| 128 | +contains the list of the monkey-patched methods. If the method value is false no response is expected, otherwise |
| 129 | +the calls provide a response. An optional pre-send processing on the background end and post-receive processing |
| 130 | +on the injected end is possible to treat values that cannot be sent as-is via the messaging protocol. |
| 131 | + |
| 132 | +The background process registers message listeners in [*messaging.js*](https://github.com/zotero/zotero-connectors/blob/e1a16c8ad2e17c6893554c3f376384e18182202d/src/common/messaging.js). |
| 133 | +`Zotero.Messaging` class also provides a way to send messages to injected scripts and add custom message listeners. |
| 134 | + |
| 135 | +The injected scripts monkey-patch methods in *messaging_injected.js*([BrowserExt](https://github.com/zotero/zotero-connectors/blob/e1a16c8ad2e17c6893554c3f376384e18182202d/src/browserExt/messaging_inject.js)/[Safari](https://github.com/zotero/zotero-connectors/blob/e1a16c8ad2e17c6893554c3f376384e18182202d/src/safari/messaging_inject.js)) |
| 136 | +`Zotero.Messaging` class also provides a way to send messages to the background process and add message listeners. |
| 137 | + |
| 138 | +## Contact |
| 139 | + |
| 140 | +If you have any questions about developing Zotero Connectors you can join the discussion in the |
| 141 | +[zotero-dev mailing list](https://groups.google.com/forum/#!forum/zotero-dev). |
0 commit comments