├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── img ├── oa128.png ├── static_spin_orange_32.png ├── static_spin_orange_32_r1.png └── static_spin_orange_32_r2.png ├── js └── oab.js └── manifest.json /.gitignore: -------------------------------------------------------------------------------- 1 | ### Packed Extension 2 | .xpi 3 | 4 | ### Vim template 5 | [._]*.s[a-w][a-z] 6 | [._]s[a-w][a-z] 7 | *.un~ 8 | Session.vim 9 | .netrwhist 10 | *~ 11 | 12 | ### OSX template 13 | .DS_Store 14 | .AppleDouble 15 | .LSOverride 16 | 17 | # Icon must end with two \r 18 | Icon 19 | 20 | # Thumbnails 21 | ._* 22 | 23 | # Files that might appear in the root of a volume 24 | .DocumentRevisions-V100 25 | .fseventsd 26 | .Spotlight-V100 27 | .TemporaryItems 28 | .Trashes 29 | .VolumeIcon.icns 30 | 31 | # Directories potentially created on remote AFP share 32 | .AppleDB 33 | .AppleDesktop 34 | Network Trash Folder 35 | Temporary Items 36 | .apdisk 37 | ### JetBrains template 38 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 39 | 40 | *.iml 41 | 42 | ## Directory-based project format: 43 | .idea/ 44 | # if you remove the above rule, at least ignore the following: 45 | 46 | # User-specific stuff: 47 | # .idea/workspace.xml 48 | # .idea/tasks.xml 49 | # .idea/dictionaries 50 | 51 | # Sensitive or high-churn files: 52 | # .idea/dataSources.ids 53 | # .idea/dataSources.xml 54 | # .idea/sqlDataSources.xml 55 | # .idea/dynamic.xml 56 | # .idea/uiDesigner.xml 57 | 58 | # Gradle: 59 | # .idea/gradle.xml 60 | # .idea/libraries 61 | 62 | # Mongo Explorer plugin: 63 | # .idea/mongoSettings.xml 64 | 65 | ## File-based project format: 66 | *.ipr 67 | *.iws 68 | 69 | ## Plugin-specific files: 70 | 71 | # IntelliJ 72 | /out/ 73 | 74 | # mpeltonen/sbt-idea plugin 75 | .idea_modules/ 76 | 77 | # JIRA plugin 78 | atlassian-ide-plugin.xml 79 | 80 | # Crashlytics plugin (for Android Studio and IntelliJ) 81 | com_crashlytics_export_strings.xml 82 | crashlytics.properties 83 | crashlytics-build.properties 84 | ### Linux template 85 | 86 | # KDE directory preferences 87 | .directory 88 | 89 | # Linux trash folder which might appear on any partition or disk 90 | .Trash-* 91 | 92 | # Created by .ignore support plugin (hsz.mobi) 93 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule ".build"] 2 | path = .build 3 | url = git@github.com:Steven-Eardley/chrome-to-firefox.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Open Access Button 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open Access Button Unified Extension 2 | =============== 3 | 4 | This is the Button's WebExtension which runs on Firefox and Chrome (and maybe Opera) which encapsulates functionality of the incumbent [Open Access Button](https://github.com/OAButton/oab-chromeaddon) and [Open Data Button](https://github.com/OAButton/odb-chromeaddon). 5 | 6 | ## Contributing 7 | 8 | Our [main repository](https:www.github.org/oabutton/discussion) contains far more information on the project, how to contribute etc. 9 | 10 | Quick guide: 11 | 12 | * If you have an issue (e.g bug, suggestion, question), make it [here](https://github.com/OAButton/discussion/issues/new) 13 | * If you want to contribute code to the plugin do it in this repository. Pull requests are always welcome. Some useful information is below. 14 | 15 | # Development notes 16 | 17 | ### Branches, master vs develop. 18 | 19 | * master is our stable, released code. 20 | * develop is what we're currently working on now. 21 | 22 | ## packaging for Firefox 23 | 24 | Firefox requires extra keys in the manifest, and the project files zip archived with extension ```.xpi```. The script ```pack.py``` does this. 25 | 26 | ## Install from development 27 | 28 | ### Getting the latest extension 29 | 30 | * Go to code page for this repo page, [plugin](https://github.com/oabutton/plugin/). 31 | * Be sure you are on the develop branch, if not, switch to develop in the drop down option on the top left of the page. 32 | * click the big green button on the top right that says 'clone or download'. 33 | * click download to get a zip file of the latest extension. 34 | * Download the zip. 35 | * Navigate and find the file on your computer, double click it to unzip it. You now have the latest code. 36 | 37 | However, we commonly use releases on this repository. It may be better to use a recent release, which can be found [here](https://github.com/OAButton/plugin/releases) 38 | Pre-releases are on dev, other releases are on live. 39 | 40 | #### Or, for leet coders 41 | 42 | * git clone 43 | * git checkout develop 44 | 45 | ### Installing the file on Chrome 46 | 47 | * In Chrome, go to chrome://extensions via the url bar, tick the 'Developer mode' tick-box in the top right corner. 48 | * Click the newly appeared 'Load unpacked extension...' button 49 | * Browse to the project directory you just downloaded, click 'Select'. It will upload the zip file you just downloaded. 50 | * If you're experiencing problems with any of these steps, feel free to leave an issue on the discussion repository [here](https://github.com/OAButton/discussion/issues/new). 51 | 52 | ## Managing releases 53 | 54 | * Only releases tagged "Release" can be put in the Chrome Store. Anything tagged "pre-release" will only work in development. Any time we want to release something new out to chrome, it will always be the latest live release that can be pushed to the chrome store. 55 | * Releases can be made through the Chrome store here: https://chrome.google.com/webstore/category/extensions while logged into the leads Open Access Button Account. 56 | * Releases should be tested on master, just in case, after release. 57 | * Releases tagged pre-release will increment whenever we push new features/fixes etc, and the most recent pre-release should be used for testing, then once testing is confirmed, we will make a live release. 58 | * Firefox packages are similar - ones in pre-release on dev will connect to the dev API. Live releases, on master, will connect to the live API 59 | -------------------------------------------------------------------------------- /img/oa128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaworks/plugin/9c19b259600e76546a2601c7e481fc04d9eabfe3/img/oa128.png -------------------------------------------------------------------------------- /img/static_spin_orange_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaworks/plugin/9c19b259600e76546a2601c7e481fc04d9eabfe3/img/static_spin_orange_32.png -------------------------------------------------------------------------------- /img/static_spin_orange_32_r1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaworks/plugin/9c19b259600e76546a2601c7e481fc04d9eabfe3/img/static_spin_orange_32_r1.png -------------------------------------------------------------------------------- /img/static_spin_orange_32_r2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaworks/plugin/9c19b259600e76546a2601c7e481fc04d9eabfe3/img/static_spin_orange_32_r2.png -------------------------------------------------------------------------------- /js/oab.js: -------------------------------------------------------------------------------- 1 | 2 | var oabutton_site_address = 'https://openaccessbutton.org'; 3 | var oabutton_running = false; 4 | var oabutton_ui = function(debug, bookmarklet, api_address, site_address) { 5 | // don't do anything if already running, probably a user pressed the button twice in quick succession 6 | console.log('oabutton UI', oabutton_running); 7 | if (oabutton_running) return; 8 | oabutton_running = true; 9 | 10 | if (bookmarklet === undefined) bookmarklet = false; // this script is also used by a bookmarklet, which sets this to a version to change plugin type 11 | if (typeof debug !== 'boolean') debug = false; 12 | if (debug) { 13 | if (api_address === undefined) api_address = 'https://beta.oa.works'; 14 | oabutton_site_address = 'https://dev.openaccessbutton.org'; 15 | } 16 | if (api_address === undefined) api_address = 'https://api.oa.works'; 17 | if (site_address !== undefined) oabutton_site_address = site_address; 18 | 19 | try { 20 | chrome.action.setIcon({path:"../img/static_spin_orange_32.png"}); 21 | var oabutton_rotate_next = 1; 22 | function oabutton_rotate() { 23 | var path = '../img/static_spin_orange_32'; 24 | if (oabutton_rotate_next === 1) { 25 | path += '_r1'; 26 | oabutton_rotate_next = 2; 27 | } else if (oabutton_rotate_next === 2) { 28 | path += '_r2'; 29 | oabutton_rotate_next = 0; 30 | } else if (oabutton_rotate_next === 0) { 31 | oabutton_rotate_next = 1; 32 | } 33 | path += '.png'; 34 | chrome.action.setIcon({ path: path }); 35 | if (oabutton_rotate_next !== false) setTimeout(oabutton_rotate, 100); 36 | } 37 | oabutton_rotate(); 38 | } catch(err) {} 39 | 40 | async function availability(data) { 41 | console.log('availability', data); 42 | try { 43 | var manifest = chrome.runtime.getManifest(); 44 | data.plugin = manifest.version_name; 45 | } catch (err) { 46 | data.plugin = bookmarklet ? 'bookmarklet_'+bookmarklet : 'oab_test_page'; 47 | } 48 | if (debug) data.test = true; 49 | resp = await fetch(api_address + '/availability', { 50 | method: 'POST', 51 | headers: { 52 | 'Content-Type': 'application/json', 53 | }, 54 | body: JSON.stringify(data), 55 | }); 56 | 57 | if (resp.status === 200) { 58 | response = await resp.json(); 59 | if (bookmarklet) document.getElementById('iconloading').style.display = 'none'; 60 | for ( var avail_entry of response.data.availability ) { 61 | if (avail_entry.type === 'article') { 62 | if (bookmarklet) { 63 | document.getElementById('isopen').style.display = 'inline'; 64 | document.getElementById('linkopen').setAttribute('href',avail_entry.url); 65 | debug ? alert('Would auto-trigger link open click now if not in debug mode') : document.getElementById('linkopen').click(); 66 | } 67 | if (chrome && chrome.tabs) chrome.tabs.create({'url': avail_entry.url}); 68 | } 69 | } 70 | for (var requests_entry of response.data.requests) { 71 | if (requests_entry.type === 'article') { 72 | if (bookmarklet) { 73 | document.getElementById('isclosed').style.display = 'inline'; 74 | document.getElementById('linkclosed').setAttribute('href',oabutton_site_address + '/request/' + requests_entry._id); 75 | debug ? alert('Would auto-trigger link closed click now if not in debug mode') : document.getElementById('linkclosed').click(); 76 | } 77 | if (chrome && chrome.tabs) chrome.tabs.create({'url': oabutton_site_address + '/request/' + requests_entry._id}); 78 | } 79 | } 80 | for (var accepts_entry of response.data.accepts) { 81 | if (accepts_entry.type === 'article') { 82 | var mu = bookmarklet ? window.location.href : response.data.match; 83 | var rurl = oabutton_site_address + '/request?url=' + encodeURIComponent(mu); 84 | if (response.data.exlibris && response.data.meta && response.data.meta.article) { 85 | if (response.data.meta.article.title) rurl += '&title=' + response.data.meta.article.title; 86 | if (response.data.meta.article.doi) rurl += '&doi=' + response.data.meta.article.doi; 87 | rurl += '&exlibris=true'; 88 | } 89 | if (bookmarklet) { 90 | document.getElementById('isclosed').style.display = 'inline'; 91 | document.getElementById('linkclosed').setAttribute('href',rurl); 92 | debug ? alert('Would auto-trigger link closed click now if not in debug mode') : document.getElementById('linkclosed').click(); 93 | } 94 | if (chrome && chrome.tabs) chrome.tabs.create({'url': rurl}); 95 | } 96 | } 97 | } else { 98 | try { 99 | var redir = resp.status === 400 ? oabutton_site_address + '/instructions#blacklist' : oabutton_site_address + '/feedback?code=' + resp.status; 100 | if (bookmarklet) { 101 | document.getElementById('iconloading').style.display = 'none'; 102 | document.getElementById('iserror').style.display = 'inline'; 103 | document.getElementById('linkerror').setAttribute('href',redir); 104 | debug ? alert('Would auto-trigger link error click now if not in debug mode') : document.getElementById('linkerror').click(); 105 | } 106 | if (chrome && chrome.tabs) chrome.tabs.create({'url': redir}); 107 | } catch (err) {} 108 | } 109 | 110 | oabutton_running = false; 111 | try { 112 | if (chrome && chrome.action) { 113 | oabutton_rotate_next = false; 114 | setTimeout(function() { chrome.action.setIcon({path:"../img/oa128.png"}); }, 1000); 115 | } 116 | } catch(err) {} 117 | } 118 | 119 | if (bookmarklet) { 120 | if (debug) console.log('Sending availability query direct from within page'); 121 | availability({url:window.location.href.split('#')[0], dom: document.all[0].outerHTML}); 122 | } else if (chrome && chrome.tabs) { 123 | chrome.tabs.query({ active: true, currentWindow: true }, async (tabs) => { 124 | var qry = {url: tabs[0].url.split('#')[0]}; 125 | try { 126 | qry.dom = (await chrome.scripting.executeScript({ 127 | target: {tabId: tabs[0].id}, 128 | function: function() { 129 | return document.all[0].outerHTML; 130 | } 131 | }))[0].result; 132 | } catch (err) {} 133 | try { 134 | qry.dom = qry.dom.replace(/)<[^<]*)*<\/script>/gi, ''); 135 | } catch (err) {} 136 | availability(qry); 137 | }); 138 | } 139 | 140 | }; 141 | 142 | try { 143 | if (chrome && chrome.action) { 144 | chrome.action.onClicked.addListener(oabutton_ui); 145 | chrome.runtime.setUninstallURL(oabutton_site_address + '/feedback#uninstall'); 146 | function instruct() { 147 | chrome.tabs.create({'url': oabutton_site_address + '/instructions'}); 148 | } 149 | chrome.runtime.onInstalled.addListener(instruct); 150 | } 151 | } catch(err) {} 152 | 153 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Open Access Button", 3 | "short_name": "OAbutton", 4 | "version": "5.0.0", 5 | "version_name": "oabutton_5.0.0", 6 | "manifest_version": 3, 7 | "description": "Push Button. Get Research. Make Progress.", 8 | "icons": { 9 | "128": "img/oa128.png" 10 | }, 11 | "background" : { "service_worker" : "js/oab.js" }, 12 | "action": { 13 | "default_title": "Open Access Button", 14 | "default_icon": "img/oa128.png" 15 | }, 16 | "permissions": [ 17 | "activeTab", 18 | "scripting" 19 | ] 20 | } 21 | --------------------------------------------------------------------------------