├── background.js ├── content-script.js ├── manifest.json ├── options.html └── options.js /background.js: -------------------------------------------------------------------------------- 1 | browser.contextMenus.create({ 2 | id: "send-to-aria2", 3 | title: "Send to Aria2 Directly", 4 | contexts: ["link"], 5 | }); 6 | browser.contextMenus.create({ 7 | id: "send-to-aria2-saveas", 8 | title: "Send to Aria2 Save As ...", 9 | contexts: ["link"], 10 | }); 11 | 12 | var S2A2_Notification_ID = "S2A2-notification"; 13 | var S2A2_Notification_timeout_ID; 14 | function S2A2_notify(title, cont) { 15 | browser.notifications.create(S2A2_Notification_ID, { 16 | "type": "basic", 17 | //"iconUrl": browser.extension.getURL("icons/cake-96.png"), 18 | "title": title, 19 | "message": cont 20 | }).then(()=>{ 21 | S2A2_Notification_timeout_ID = setTimeout(() => { 22 | browser.notifications.clear(S2A2_Notification_ID); 23 | }, 5000); 24 | }); 25 | } 26 | 27 | function S2A2_xmlhttpRequest(aria2server, aria2secret, dlurl, filename) { 28 | try { 29 | var oReq = new XMLHttpRequest(); 30 | var dlparams = {} 31 | if (filename) dlparams['out'] = filename; 32 | 33 | jsonreq = {'jsonrpc':'2.0', 34 | 'id':'qwer', 35 | 'method':'aria2.addUri', 36 | 'params': [[dlurl],dlparams]} 37 | if (aria2secret) { 38 | jsonreq.params.splice(0,0,'token:' + aria2secret) 39 | } 40 | jsonreqstr = JSON.stringify(jsonreq); 41 | // open synchronously 42 | oReq.open("post",aria2server,false); 43 | 44 | oReq.onload = function(e) { 45 | if (this.status == 200) { 46 | var resobj = JSON.parse(this.responseText); 47 | S2A2_notify("SendToAria2 Successfully", 'GID: ' + resobj.result + ( 48 | filename ? "\n" + filename: '')); 49 | } else { 50 | S2A2_notify("SendToAria2 ERROR", this.responseText); 51 | } 52 | }; 53 | // send 54 | var res = oReq.send(jsonreqstr); 55 | //console.log('xhr result: %s', res); 56 | } catch(e) { 57 | //debugger; 58 | console.warn('could not send ajax request, reason %s', e.toString()); 59 | S2A2_notify("SendToAria2 ERROR", e.toString()); 60 | } 61 | } 62 | 63 | function S2A2_mkjob(dlurl, filename) { 64 | var pr = browser.storage.local.get('aria2server'); 65 | var pt = browser.storage.local.get('aria2secret'); 66 | Promise.all([pr,pt]).then((res) => { 67 | S2A2_xmlhttpRequest(res[0]['aria2server'],res[1]['aria2secret'],dlurl,filename) 68 | }).catch (reason=>{ 69 | pr.then((res) => { 70 | S2A2_xmlhttpRequest(res['aria2server'],null,dlurl,filename) 71 | }); 72 | }); 73 | } 74 | 75 | browser.contextMenus.onClicked.addListener((info, tab) => { 76 | if (info.menuItemId === "send-to-aria2-saveas") { 77 | // Examples: text and HTML to be copied. 78 | // const text = "This is text: " + info.linkUrl; 79 | // Always HTML-escape external input to avoid XSS. 80 | const safeUrl = escapeHTML(info.linkUrl); 81 | 82 | browser.tabs.sendMessage(tab.id, safeUrl); 83 | } else if (info.menuItemId === "send-to-aria2") { 84 | S2A2_mkjob(escapeHTML(info.linkUrl), null); 85 | } 86 | }); 87 | 88 | browser.runtime.onMessage.addListener(function (info) { 89 | S2A2_mkjob(info.url, info.filename); 90 | }); 91 | 92 | 93 | // https://gist.github.com/Rob--W/ec23b9d6db9e56b7e4563f1544e0d546 94 | function escapeHTML(str) { 95 | // Note: string cast using String; may throw if `str` is non-serializable, e.g. a Symbol. 96 | // Most often this is not the case though. 97 | return String(str) 98 | .replace(/&/g, "&") 99 | .replace(/"/g, """).replace(/'/g, "'") 100 | .replace(//g, ">"); 101 | } -------------------------------------------------------------------------------- /content-script.js: -------------------------------------------------------------------------------- 1 | 2 | function S2A2_getfilename(dlurl) { 3 | var filename = window.top.prompt("[Send To Aria2] Save As Filename",""); 4 | var sendto = true; 5 | if (filename==null || filename.length==0) { 6 | var sendtowithblank = window.top.prompt("Send to Aria2 Directly? \"Cancel\" to cancel this Action."); 7 | if (!sendtowithblank) sendto = false; 8 | } 9 | if (sendto) { 10 | browser.runtime.sendMessage({"url": dlurl, "filename":filename}); 11 | } 12 | } 13 | 14 | browser.runtime.onMessage.addListener(S2A2_getfilename); 15 | 16 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "manifest_version": 2, 4 | "name": "Send to Aria2 WE", 5 | "description": "Send to Aria2 server's json-rpc api", 6 | 7 | "version": "0.3", 8 | "homepage_url": "https://github.com/wadefelix/SendToAria2", 9 | 10 | "developer": { 11 | "name": "Ren Wei" 12 | }, 13 | 14 | "background": { 15 | "scripts": ["background.js"] 16 | }, 17 | 18 | "content_scripts": [ 19 | { 20 | "matches": [""], 21 | "js": ["content-script.js"], 22 | "run_at": "document_end" 23 | } 24 | ], 25 | 26 | "permissions": [ 27 | "contextMenus", 28 | "activeTab", 29 | "tabs", 30 | "storage", 31 | "notifications" 32 | ], 33 | "options_ui": { 34 | "page": "options.html" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 | Options 12 |

aria2 server json rpc, such as http://192.168.1.4:6800/jsonrpc

13 | 14 | 15 | 16 |
json-rpc
rpc-secret
17 | 18 |
19 |
20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /options.js: -------------------------------------------------------------------------------- 1 | function saveOptions(e) { 2 | browser.storage.local.set({ 3 | aria2server: document.querySelector("#aria2server").value 4 | }); 5 | browser.storage.local.set({ 6 | aria2secret: document.querySelector("#aria2secret").value 7 | }); 8 | e.preventDefault(); 9 | } 10 | 11 | function restoreOptions() { 12 | browser.storage.local.get('aria2server').then((res) => { 13 | document.querySelector("#aria2server").value = res.aria2server || ''; 14 | }); 15 | browser.storage.local.get('aria2secret').then((res) => { 16 | document.querySelector("#aria2secret").value = res.aria2secret || ''; 17 | }); 18 | } 19 | 20 | document.addEventListener('DOMContentLoaded', restoreOptions); 21 | document.querySelector("form").addEventListener("submit", saveOptions); 22 | --------------------------------------------------------------------------------