release\
6
README.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
Download With Extension
|
||||
================
|
||||
|
||||
Download With is an extension that overrides the default download operation and instead sends it to a defined external program. It's based off code from [OpenWith](https://github.com/darktrojan/openwith) and used it as the foundation.
|
||||
|
||||
The purpose of this addon is to bring back support for your own external download manager, without having to use a specific program with included integrations.
|
43
action.css
Normal file
|
@ -0,0 +1,43 @@
|
|||
body {
|
||||
min-width: 180px;
|
||||
}
|
||||
#update,
|
||||
#warning,
|
||||
#error,
|
||||
#nobrowsers {
|
||||
display: none;
|
||||
margin: 4px;
|
||||
padding: 8px;
|
||||
color: #fff;
|
||||
line-height: 1.4;
|
||||
text-align: center;
|
||||
}
|
||||
#update {
|
||||
background-color: #0e9352;
|
||||
}
|
||||
#update_message {
|
||||
max-width: 280px;
|
||||
margin: 0 auto 8px;
|
||||
}
|
||||
#warning {
|
||||
background-color: #fec82f;
|
||||
}
|
||||
#error {
|
||||
background-color: #e82727;
|
||||
}
|
||||
#nobrowsers {
|
||||
color: #222426;
|
||||
}
|
||||
#browsers {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.name {
|
||||
-webkit-margin-start: 8px;
|
||||
margin-inline-start: 8px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.panel-section-footer-button {
|
||||
margin: 0;
|
||||
}
|
37
action.html
Normal file
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" type="text/css" href="action_browser.css" />
|
||||
<link rel="stylesheet" type="text/css" href="action.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="panel">
|
||||
<div id="update" class="panel-section">
|
||||
<div id="update_message"></div>
|
||||
<div>
|
||||
<button data-message="update_changelog_button"></button>
|
||||
<button data-message="donate_button"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="warning" class="panel-section" data-message="update_warning"></div>
|
||||
<div id="error" class="panel-section" data-message="update_error"></div>
|
||||
<div class="panel-section panel-section-list">
|
||||
<div id="nobrowsers" class="panel-section" data-message="popup_nobrowsers"></div>
|
||||
<ul id="browsers">
|
||||
<template>
|
||||
<li class="panel-list-item">
|
||||
<img class="icon" width="16" height="16" />
|
||||
<div class="name text"></div>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel-section panel-section-footer">
|
||||
<div class="panel-section-footer-button" data-message="popup_options_button"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="common.js"></script>
|
||||
<script type="text/javascript" src="action.js"></script>
|
||||
</body>
|
||||
</html>
|
117
action.js
Normal file
|
@ -0,0 +1,117 @@
|
|||
/* globals chrome, get_string, get_strings, is_same_colour, ERROR_COLOUR, WARNING_COLOUR */
|
||||
let errorMessage = document.getElementById('error');
|
||||
let warningMessage = document.getElementById('warning');
|
||||
let updateMessage = document.getElementById('update');
|
||||
let browsersList = document.getElementById('browsers');
|
||||
let browsersTemplate = browsersList.querySelector('template');
|
||||
|
||||
get_strings();
|
||||
|
||||
chrome.browserAction.getBadgeBackgroundColor({}, function(colour) {
|
||||
chrome.browserAction.setBadgeText({text: ''});
|
||||
chrome.browserAction.setBadgeBackgroundColor({color: [0, 0, 0, 0]});
|
||||
|
||||
if (is_same_colour(colour, ERROR_COLOUR)) {
|
||||
errorMessage.style.display = 'block';
|
||||
} else if (is_same_colour(colour, WARNING_COLOUR)) {
|
||||
warningMessage.style.display = 'block';
|
||||
} else {
|
||||
chrome.management.getSelf(function({version: currentVersion}) {
|
||||
let now = new Date();
|
||||
|
||||
chrome.storage.local.get({
|
||||
versionLastUpdate: '1970-01-01T00:00:00.000Z',
|
||||
versionLastAck: '1970-01-01T00:00:00.000Z'
|
||||
}, function({versionLastUpdate, versionLastAck}) {
|
||||
if (typeof versionLastUpdate == 'string') {
|
||||
versionLastUpdate = new Date(versionLastUpdate);
|
||||
}
|
||||
if (typeof versionLastAck == 'string') {
|
||||
versionLastAck = new Date(versionLastAck);
|
||||
}
|
||||
if (now - versionLastUpdate < 43200000 && now - versionLastAck > 604800000) {
|
||||
document.getElementById('update_message').textContent = get_string('update_message', currentVersion);
|
||||
updateMessage.style.display = 'block';
|
||||
}
|
||||
chrome.storage.local.set({
|
||||
versionLastUpdate: versionLastUpdate.toJSON(),
|
||||
versionLastAck: versionLastAck.toJSON()
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let userIcons = new Map();
|
||||
chrome.runtime.sendMessage({action: 'get_icons'}, function(result) {
|
||||
for (let l of result) {
|
||||
userIcons.set(l.id.toString(), l);
|
||||
}
|
||||
|
||||
chrome.runtime.sendMessage({action: 'get_browsers'}, function(browsers) {
|
||||
if (browsers.length === 0) {
|
||||
document.getElementById('nobrowsers').style.display = 'block';
|
||||
}
|
||||
for (let b of browsers) {
|
||||
if (b.hidden) {
|
||||
continue;
|
||||
}
|
||||
add_browser(b);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
browsersList.onclick = function(event) {
|
||||
let target = event.target;
|
||||
while (target && target.localName != 'li') {
|
||||
target = target.parentNode;
|
||||
}
|
||||
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
|
||||
chrome.runtime.sendMessage({
|
||||
action: 'open_browser',
|
||||
id: target.dataset.id,
|
||||
url: event.ctrlKey ? null : tabs[0].url
|
||||
});
|
||||
window.close();
|
||||
});
|
||||
};
|
||||
|
||||
updateMessage.onclick = function({target}) {
|
||||
chrome.storage.local.set({versionLastAck: new Date().toJSON()});
|
||||
switch (target.dataset.message) {
|
||||
case 'update_changelog_button':
|
||||
chrome.management.getSelf(function({version}) {
|
||||
chrome.tabs.create({url: 'https://addons.mozilla.org/addon/open-with/versions/' + version});
|
||||
});
|
||||
return;
|
||||
case 'donate_button':
|
||||
chrome.tabs.create({url: 'https://darktrojan.github.io/donate.html?openwith'});
|
||||
return;
|
||||
}
|
||||
open_options_tab();
|
||||
};
|
||||
errorMessage.onclick = warningMessage.onclick = function() {
|
||||
chrome.storage.local.set({versionLastAck: new Date().toJSON()});
|
||||
open_options_tab();
|
||||
};
|
||||
document.querySelector('.panel-section-footer-button').onclick = open_options_tab;
|
||||
|
||||
function open_options_tab() {
|
||||
chrome.runtime.openOptionsPage(function() {
|
||||
window.close();
|
||||
});
|
||||
}
|
||||
|
||||
function add_browser(b) {
|
||||
let li = browsersTemplate.content.firstElementChild.cloneNode(true);
|
||||
li.dataset.id = b.id;
|
||||
if ('icon' in b && b.icon) { // b.icon could be undefined if we stuffed up (#170)
|
||||
if (b.icon.startsWith('user_icon_')) {
|
||||
li.querySelector('img').src = userIcons.get(b.icon.substring(10))['16'];
|
||||
} else {
|
||||
li.querySelector('img').src = 'icons/' + b.icon + '_16x16.png';
|
||||
}
|
||||
}
|
||||
li.querySelector('div.name').textContent = b.name;
|
||||
browsersList.appendChild(li);
|
||||
}
|
75
action_browser.css
Normal file
|
@ -0,0 +1,75 @@
|
|||
html,
|
||||
body {
|
||||
background: transparent;
|
||||
box-sizing: border-box;
|
||||
color: #222426;
|
||||
cursor: default;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
font: message-box;
|
||||
font-size: 13.333px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
body * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
button {
|
||||
font-size: 13.333px;
|
||||
}
|
||||
.panel-section {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.panel-section-list {
|
||||
flex-direction: column;
|
||||
padding: 4px 0;
|
||||
}
|
||||
.panel-list-item {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 24px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
.panel-list-item:not(.disabled):hover {
|
||||
background-color: rgba(0, 0, 0, 0.06);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.panel-list-item:not(.disabled):hover:active {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.panel-list-item > .icon {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.panel-list-item > .text {
|
||||
flex-grow: 10;
|
||||
}
|
||||
.panel-section-footer {
|
||||
background-color: rgba(0, 0, 0, 0.06);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.15);
|
||||
color: #1a1a1a;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 41px;
|
||||
margin-top: -1px;
|
||||
padding: 0;
|
||||
}
|
||||
.panel-section-footer-button {
|
||||
flex: 1 1 auto;
|
||||
height: 100%;
|
||||
margin: 0 -1px;
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
.panel-section-footer-button:hover {
|
||||
background-color: rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.panel-section-footer-button:hover:active {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
33
background.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* globals chrome, compare_versions, get_version_warn, ERROR_COLOUR, WARNING_COLOUR */
|
||||
var exe;
|
||||
|
||||
function open_external(item) {
|
||||
function error_listener(error) {
|
||||
console.error(error, chrome.runtime.lastError);
|
||||
}
|
||||
|
||||
browser.downloads.cancel(item.id).then(
|
||||
function () {
|
||||
let command = exe.replace('%s', item.url);
|
||||
|
||||
let port = chrome.runtime.connectNative('download_with');
|
||||
port.onDisconnect.addListener(error_listener);
|
||||
port.onMessage.addListener((m) => {
|
||||
console.log(m);
|
||||
port.onDisconnect.removeListener(error_listener);
|
||||
port.disconnect();
|
||||
});
|
||||
console.log('executing: '+command);
|
||||
port.postMessage(command.split(' '));
|
||||
},
|
||||
function (err) {
|
||||
console.log(`download_with: Could not cancel ${item.filename} (${item.id}): Error: ${err}`);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
chrome.storage.local.get({execute: null}, function({execute}) {
|
||||
exe = execute;
|
||||
});
|
||||
|
||||
browser.downloads.onCreated.addListener(open_external);
|
89
common.js
Normal file
|
@ -0,0 +1,89 @@
|
|||
/* globals chrome */
|
||||
/* exported get_version_warn, compare_versions, compare_object_versions, get_string, get_strings,
|
||||
ERROR_COLOUR, WARNING_COLOUR, is_same_colour */
|
||||
var _version_warn = null;
|
||||
async function get_version_warn() {
|
||||
if (!!_version_warn) {
|
||||
return _version_warn;
|
||||
}
|
||||
|
||||
if ('browser' in this && 'runtime' in this.browser && 'getBrowserInfo' in this.browser.runtime) {
|
||||
browserInfo = await browser.runtime.getBrowserInfo();
|
||||
if (browserInfo.name == 'Thunderbird') {
|
||||
return '7.2.3';
|
||||
}
|
||||
}
|
||||
|
||||
return '0.0.1';
|
||||
|
||||
// return new Promise(function(resolve) {
|
||||
// chrome.runtime.getPlatformInfo(function(platformInfo) {
|
||||
// _version_warn = platformInfo.os == 'win' ? '7.0.1' : '7.0b10';
|
||||
// resolve(_version_warn);
|
||||
// });
|
||||
// });
|
||||
}
|
||||
|
||||
function compare_versions(a, b) {
|
||||
function split_apart(name) {
|
||||
var parts = [];
|
||||
var lastIsDigit = false;
|
||||
var part = '';
|
||||
for (let c of name.toString()) {
|
||||
let currentIsDigit = c >= '0' && c <= '9';
|
||||
if (c == '.' || lastIsDigit != currentIsDigit) {
|
||||
if (part) {
|
||||
parts.push(lastIsDigit ? parseInt(part, 10) : part);
|
||||
}
|
||||
part = c == '.' ? '' : c;
|
||||
} else {
|
||||
part += c;
|
||||
}
|
||||
lastIsDigit = currentIsDigit;
|
||||
}
|
||||
if (part) {
|
||||
parts.push(lastIsDigit ? parseInt(part, 10) : part);
|
||||
}
|
||||
return parts;
|
||||
}
|
||||
function compare_parts(x, y) {
|
||||
let xType = typeof x;
|
||||
let yType = typeof y;
|
||||
|
||||
switch (xType) {
|
||||
case yType:
|
||||
return x == y ? 0 : (x < y ? -1 : 1);
|
||||
case 'string':
|
||||
return -1;
|
||||
case 'undefined':
|
||||
return yType == 'number' ? (y === 0 ? 0 : -1) : 1;
|
||||
case 'number':
|
||||
return x === 0 && yType == 'undefined' ? 0 : 1;
|
||||
}
|
||||
}
|
||||
let aParts = split_apart(a);
|
||||
let bParts = split_apart(b);
|
||||
for (let i = 0; i <= aParts.length || i <= bParts.length; i++) {
|
||||
let comparison = compare_parts(aParts[i], bParts[i]);
|
||||
if (comparison !== 0) {
|
||||
return comparison;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function compare_object_versions(a, b) {
|
||||
return compare_versions(a.name, b.name);
|
||||
}
|
||||
|
||||
var ERROR_COLOUR = [232, 39, 39, 255];
|
||||
var WARNING_COLOUR = [254, 200, 47, 255];
|
||||
|
||||
function is_same_colour(a, b) {
|
||||
for (let i = 0; i < 4; i++) {
|
||||
if (a[i] != b[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
BIN
images/128.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
images/16.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
images/24.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
images/32.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
images/48.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
images/64.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
images/96.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
41
installed.css
Normal file
|
@ -0,0 +1,41 @@
|
|||
body {
|
||||
min-width: 25em;
|
||||
}
|
||||
div.panel {
|
||||
display: flex;
|
||||
}
|
||||
div.panel > div {
|
||||
padding: 8px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
div.panel > div:last-child {
|
||||
flex-grow: 1;
|
||||
}
|
||||
div#header {
|
||||
font-weight: 600;
|
||||
}
|
||||
a {
|
||||
color: #0454d4;
|
||||
}
|
||||
div#button {
|
||||
margin-top: 8px;
|
||||
text-align: right;
|
||||
}
|
||||
button {
|
||||
background-color: #fbfbfb;
|
||||
border: 1px solid #b1b1b1;
|
||||
box-shadow: 0 0 0 0 transparent;
|
||||
height: 24px;
|
||||
outline: 0 !important;
|
||||
padding: 0 8px 0;
|
||||
transition-duration: 250ms;
|
||||
transition-property: box-shadow, border;
|
||||
}
|
||||
button:hover {
|
||||
background-color: #ebebeb;
|
||||
border: 1px solid #b1b1b1;
|
||||
}
|
||||
button:hover:active {
|
||||
background-color: #d4d4d4;
|
||||
border: 1px solid #858585;
|
||||
}
|
25
installed.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" type="text/css" href="action_browser.css" />
|
||||
<link rel="stylesheet" type="text/css" href="installed.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="panel">
|
||||
<div>
|
||||
<img src="images/openwith.svg" width="64" height="64" />
|
||||
</div>
|
||||
<div>
|
||||
<div id="header" data-message="popup_installed_header2"></div>
|
||||
<div data-message="popup_installed_text"></div>
|
||||
<div><a data-href="webextension_info_url" data-message="webextension_info_label"></a></div>
|
||||
<div id="button">
|
||||
<button data-message="popup_options_button"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="common.js"></script>
|
||||
<script type="text/javascript" src="installed.js"></script>
|
||||
</body>
|
||||
</html>
|
8
installed.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* globals chrome, get_strings */
|
||||
get_strings();
|
||||
|
||||
document.querySelector('button').onclick = function() {
|
||||
chrome.runtime.openOptionsPage(function() {
|
||||
window.close();
|
||||
});
|
||||
};
|
38
manifest.json
Normal file
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Download With",
|
||||
"description": "Set an external manager for your downloads.",
|
||||
"version": "0.0.1",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "downloadwith@wirlaburla.github.io",
|
||||
"strict_min_version": "63.0"
|
||||
}
|
||||
},
|
||||
"icons": {
|
||||
"16": "images/16.png",
|
||||
"24": "images/24.png",
|
||||
"32": "images/32.png",
|
||||
"48": "images/48.png",
|
||||
"64": "images/64.png",
|
||||
"96": "images/96.png",
|
||||
"128": "images/128.png"
|
||||
},
|
||||
"background": {
|
||||
"scripts": [
|
||||
"common.js",
|
||||
"background.js"
|
||||
]
|
||||
},
|
||||
"permissions": [
|
||||
"downloads",
|
||||
"nativeMessaging",
|
||||
"storage",
|
||||
"tabs"
|
||||
],
|
||||
"options_ui": {
|
||||
"browser_style": false,
|
||||
"open_in_tab": true,
|
||||
"page": "options.html"
|
||||
}
|
||||
}
|
110
native/download_with_linux.py
Executable file
|
@ -0,0 +1,110 @@
|
|||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import struct
|
||||
import subprocess
|
||||
|
||||
VERSION = '0.0.1'
|
||||
|
||||
try:
|
||||
sys.stdin.buffer
|
||||
|
||||
# Python 3.x version
|
||||
# Read a message from stdin and decode it.
|
||||
def getMessage():
|
||||
rawLength = sys.stdin.buffer.read(4)
|
||||
if len(rawLength) == 0:
|
||||
sys.exit(0)
|
||||
messageLength = struct.unpack('@I', rawLength)[0]
|
||||
message = sys.stdin.buffer.read(messageLength).decode('utf-8')
|
||||
return json.loads(message)
|
||||
|
||||
# Send an encoded message to stdout
|
||||
def sendMessage(messageContent):
|
||||
encodedContent = json.dumps(messageContent).encode('utf-8')
|
||||
encodedLength = struct.pack('@I', len(encodedContent))
|
||||
|
||||
sys.stdout.buffer.write(encodedLength)
|
||||
sys.stdout.buffer.write(encodedContent)
|
||||
sys.stdout.buffer.flush()
|
||||
|
||||
except AttributeError:
|
||||
# Python 2.x version (if sys.stdin.buffer is not defined)
|
||||
print('Python 3.2 or newer is required.')
|
||||
sys.exit(-1)
|
||||
|
||||
|
||||
def install():
|
||||
home_path = os.getenv('HOME')
|
||||
|
||||
manifest = {
|
||||
'name': 'download_with',
|
||||
'description': 'Download With native host',
|
||||
'path': os.path.realpath(__file__),
|
||||
'type': 'stdio',
|
||||
}
|
||||
locations = {
|
||||
'chrome': os.path.join(home_path, '.config', 'google-chrome', 'NativeMessagingHosts'),
|
||||
'chrome-beta': os.path.join(home_path, '.config', 'google-chrome-beta', 'NativeMessagingHosts'),
|
||||
'chrome-unstable': os.path.join(home_path, '.config', 'google-chrome-unstable', 'NativeMessagingHosts'),
|
||||
'chromium': os.path.join(home_path, '.config', 'chromium', 'NativeMessagingHosts'),
|
||||
'firefox': os.path.join(home_path, '.mozilla', 'native-messaging-hosts'),
|
||||
'librewolf': os.path.join(home_path, '.librewolf', 'native-messaging-hosts'),
|
||||
'waterfox': os.path.join(home_path, '.waterfox', 'native-messaging-hosts'),
|
||||
'waterfox-g4': os.path.join(home_path, '.waterfox', 'native-messaging-hosts'),
|
||||
'thunderbird': os.path.join(home_path, '.thunderbird', 'native-messaging-hosts'),
|
||||
}
|
||||
filename = 'download_with.json'
|
||||
|
||||
for browser, location in locations.items():
|
||||
if os.path.exists(os.path.dirname(location)):
|
||||
if not os.path.exists(location):
|
||||
os.mkdir(location)
|
||||
|
||||
browser_manifest = manifest.copy()
|
||||
if browser in ['firefox', 'thunderbird', 'librewolf', 'waterfox', 'waterfox-g4']:
|
||||
browser_manifest['allowed_extensions'] = ['downloadwith@wirlaburla.github.io']
|
||||
else:
|
||||
browser_manifest['allowed_origins'] = [
|
||||
'chrome-extension://cogjlncmljjnjpbgppagklanlcbchlno/', # Chrome
|
||||
'chrome-extension://fbmcaggceafhobjkhnaakhgfmdaadhhg/', # Opera
|
||||
]
|
||||
|
||||
with open(os.path.join(location, filename), 'w') as file:
|
||||
file.write(
|
||||
json.dumps(browser_manifest, indent=2, separators=(',', ': '), sort_keys=True).replace(' ', '\t') + '\n'
|
||||
)
|
||||
|
||||
def listen():
|
||||
receivedMessage = getMessage()
|
||||
if receivedMessage == 'ping':
|
||||
sendMessage({
|
||||
'version': VERSION,
|
||||
'file': os.path.realpath(__file__)
|
||||
})
|
||||
else:
|
||||
devnull = open(os.devnull, 'w')
|
||||
subprocess.Popen(receivedMessage, stdout=devnull, stderr=devnull)
|
||||
sendMessage(None)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) == 2:
|
||||
if sys.argv[1] == 'install':
|
||||
install()
|
||||
sys.exit(0)
|
||||
allowed_extensions = [
|
||||
'downloadwith@wirlaburla.github.io',
|
||||
'chrome-extension://cogjlncmljjnjpbgppagklanlcbchlno/',
|
||||
'chrome-extension://fbmcaggceafhobjkhnaakhgfmdaadhhg/',
|
||||
]
|
||||
for ae in allowed_extensions:
|
||||
if ae in sys.argv:
|
||||
listen()
|
||||
sys.exit(0)
|
||||
|
||||
print('This is the Download With native helper, version %s.' % VERSION)
|
||||
print('Run this script again with the word "install" after the file name to install.')
|
152
native/download_with_mac.py
Executable file
|
@ -0,0 +1,152 @@
|
|||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import struct
|
||||
import subprocess
|
||||
|
||||
VERSION = '7.2.6'
|
||||
|
||||
try:
|
||||
sys.stdin.buffer
|
||||
|
||||
# Python 3.x version
|
||||
# Read a message from stdin and decode it.
|
||||
def getMessage():
|
||||
rawLength = sys.stdin.buffer.read(4)
|
||||
if len(rawLength) == 0:
|
||||
sys.exit(0)
|
||||
messageLength = struct.unpack('@I', rawLength)[0]
|
||||
message = sys.stdin.buffer.read(messageLength).decode('utf-8')
|
||||
return json.loads(message)
|
||||
|
||||
# Send an encoded message to stdout
|
||||
def sendMessage(messageContent):
|
||||
encodedContent = json.dumps(messageContent).encode('utf-8')
|
||||
encodedLength = struct.pack('@I', len(encodedContent))
|
||||
|
||||
sys.stdout.buffer.write(encodedLength)
|
||||
sys.stdout.buffer.write(encodedContent)
|
||||
sys.stdout.buffer.flush()
|
||||
|
||||
except AttributeError:
|
||||
print('Python 3.2 or newer is required.')
|
||||
sys.exit(-1)
|
||||
|
||||
|
||||
def install():
|
||||
home_path = os.getenv('HOME')
|
||||
|
||||
manifest = {
|
||||
'name': 'open_with',
|
||||
'description': 'Open With native host',
|
||||
'path': os.path.realpath(__file__),
|
||||
'type': 'stdio',
|
||||
}
|
||||
locations = {
|
||||
'chrome': os.path.join(home_path, 'Library', 'Application Support', 'Google', 'Chrome', 'NativeMessagingHosts'),
|
||||
'chromium': os.path.join(home_path, 'Library', 'Application Support', 'Chromium', 'NativeMessagingHosts'),
|
||||
'edge': os.path.join(home_path, 'Library', 'Application Support', 'Microsoft Edge', 'NativeMessagingHosts'),
|
||||
'firefox': os.path.join(home_path, 'Library', 'Application Support', 'Mozilla', 'NativeMessagingHosts'),
|
||||
'thunderbird1': os.path.join(home_path, 'Library', 'Application Support', 'Thunderbird', 'NativeMessagingHosts'),
|
||||
'thunderbird2': os.path.join(home_path, 'Library', 'Mozilla', 'NativeMessagingHosts'),
|
||||
}
|
||||
filename = 'open_with.json'
|
||||
|
||||
for browser, location in locations.items():
|
||||
if os.path.exists(os.path.dirname(location)):
|
||||
if not os.path.exists(location):
|
||||
os.makedirs(location, exist_ok=True)
|
||||
|
||||
browser_manifest = manifest.copy()
|
||||
if browser in ['firefox', 'thunderbird1', 'thunderbird2']:
|
||||
browser_manifest['allowed_extensions'] = ['openwith@darktrojan.net']
|
||||
else:
|
||||
browser_manifest['allowed_origins'] = [
|
||||
'chrome-extension://cogjlncmljjnjpbgppagklanlcbchlno/', # Chrome
|
||||
'chrome-extension://fbmcaggceafhobjkhnaakhgfmdaadhhg/', # Opera
|
||||
]
|
||||
|
||||
with open(os.path.join(location, filename), 'w') as file:
|
||||
file.write(
|
||||
json.dumps(browser_manifest, indent=2, separators=(',', ': '), sort_keys=True).replace(' ', '\t') + '\n'
|
||||
)
|
||||
|
||||
|
||||
def find_browsers():
|
||||
apps = [
|
||||
'Chrome',
|
||||
'Chromium',
|
||||
'Firefox',
|
||||
'Google Chrome',
|
||||
'Microsoft Edge',
|
||||
'Opera',
|
||||
'Safari',
|
||||
'SeaMonkey',
|
||||
]
|
||||
paths = [
|
||||
os.path.join(os.getenv('HOME'), 'Applications'),
|
||||
'/Applications',
|
||||
]
|
||||
|
||||
results = []
|
||||
for p in paths:
|
||||
for a in apps:
|
||||
fp = os.path.join(p, a) + '.app'
|
||||
if os.path.exists(fp):
|
||||
results.append({
|
||||
'name': a,
|
||||
'command': '"%s.app"' % os.path.join(p, a)
|
||||
})
|
||||
return results
|
||||
|
||||
|
||||
def listen():
|
||||
receivedMessage = getMessage()
|
||||
if receivedMessage == 'ping':
|
||||
sendMessage({
|
||||
'version': VERSION,
|
||||
'file': os.path.realpath(__file__)
|
||||
})
|
||||
elif receivedMessage == 'find':
|
||||
sendMessage(find_browsers())
|
||||
else:
|
||||
for k, v in os.environ.items():
|
||||
if k.startswith('MOZ_'):
|
||||
try:
|
||||
os.unsetenv(k)
|
||||
except:
|
||||
os.environ[k] = ''
|
||||
|
||||
devnull = open(os.devnull, 'w')
|
||||
if receivedMessage[0].endswith('.app'):
|
||||
command = ['/usr/bin/open', '-a'] + receivedMessage
|
||||
else:
|
||||
command = receivedMessage
|
||||
subprocess.Popen(command, stdout=devnull, stderr=devnull)
|
||||
sendMessage(None)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) == 2:
|
||||
if sys.argv[1] == 'install':
|
||||
install()
|
||||
sys.exit(0)
|
||||
elif sys.argv[1] == 'find_browsers':
|
||||
print(find_browsers())
|
||||
sys.exit(0)
|
||||
|
||||
allowed_extensions = [
|
||||
'openwith@darktrojan.net',
|
||||
'chrome-extension://cogjlncmljjnjpbgppagklanlcbchlno/',
|
||||
'chrome-extension://fbmcaggceafhobjkhnaakhgfmdaadhhg/',
|
||||
]
|
||||
for ae in allowed_extensions:
|
||||
if ae in sys.argv:
|
||||
listen()
|
||||
sys.exit(0)
|
||||
|
||||
print('This is the Open With native helper, version %s.' % VERSION)
|
||||
print('Run this script again with the word "install" after the file name to install.')
|
161
native/download_with_windows.ps1
Normal file
|
@ -0,0 +1,161 @@
|
|||
function GetMessage {
|
||||
$reader = New-Object System.IO.BinaryReader([System.Console]::OpenStandardInput())
|
||||
$messageLength = $reader.ReadInt32()
|
||||
$messageBytes = $reader.ReadBytes($messageLength)
|
||||
return [System.Text.Encoding]::UTF8.GetString($messageBytes) | ConvertFrom-Json
|
||||
}
|
||||
|
||||
function SendReply {
|
||||
param ($reply)
|
||||
$replyBytes = [System.Text.Encoding]::UTF8.GetBytes(($reply | ConvertTo-Json))
|
||||
$writer = New-Object System.IO.BinaryWriter([System.Console]::OpenStandardOutput())
|
||||
$writer.Write($replyBytes.Count)
|
||||
$writer.Write($replyBytes)
|
||||
}
|
||||
|
||||
function Install {
|
||||
$registry_locations = @{
|
||||
chrome='HKCU:\Software\Google\Chrome\NativeMessagingHosts';
|
||||
firefox='HKCU:\Software\Mozilla\NativeMessagingHosts'
|
||||
}
|
||||
|
||||
$install_path = Split-Path $PSCommandPath -Parent
|
||||
$bat_path = (Join-Path $install_path -ChildPath 'open_with.bat')
|
||||
New-Item -Force -Path $bat_path -Value (@'
|
||||
@echo off
|
||||
call "powershell" -file "
|
||||
'@ + $PSCommandPath + '"') > $null
|
||||
|
||||
$manifest = @{name='open_with';type='stdio';path=$bat_path;description='Open With native host'}
|
||||
|
||||
foreach ($browser in $registry_locations.Keys) {
|
||||
$registry_location = $registry_locations[$browser]
|
||||
if (Get-Item (Split-Path $registry_location -Parent)) {
|
||||
if (!(Get-Item $registry_location -ErrorAction Ignore)) {
|
||||
New-Item $registry_location > $null
|
||||
}
|
||||
|
||||
$registry_location = Join-Path $registry_location -ChildPath 'open_with'
|
||||
$manifest_location = Join-Path $install_path -ChildPath ('open_with_' + $browser + '.json')
|
||||
if (!(Get-Item $registry_location -ErrorAction Ignore)) {
|
||||
New-Item $registry_location > $null
|
||||
}
|
||||
|
||||
Set-Item -Path $registry_location -Value $manifest_location -Force
|
||||
$browser_manifest = $manifest.Clone()
|
||||
if ($browser -eq 'firefox') {
|
||||
$browser_manifest['allowed_extensions'] = @('openwith@darktrojan.net')
|
||||
} else {
|
||||
$browser_manifest['allowed_origins'] = @('chrome-extension://cogjlncmljjnjpbgppagklanlcbchlno/')
|
||||
}
|
||||
New-Item -Force -Path $manifest_location -Value ($browser_manifest | ConvertTo-Json) > $null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function FindBrowsers {
|
||||
return (Get-ChildItem -Path 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Clients\StartMenuInternet\' |
|
||||
Select-Object -Property @{Name='name';Expression={$_.GetValue($null)}}, @{Name='command';Expression={$_.OpenSubKey('shell\open\command').GetValue($null)}})
|
||||
}
|
||||
|
||||
# From https://github.com/FuzzySecurity/PowerShell-Suite
|
||||
function Invoke-CreateProcess {
|
||||
param (
|
||||
[Parameter(Mandatory = $True)]
|
||||
[string]$Binary,
|
||||
[Parameter(Mandatory = $False)]
|
||||
[string]$Args=$null,
|
||||
[Parameter(Mandatory = $True)]
|
||||
[string]$CreationFlags,
|
||||
[Parameter(Mandatory = $True)]
|
||||
[string]$ShowWindow,
|
||||
[Parameter(Mandatory = $True)]
|
||||
[string]$StartF
|
||||
)
|
||||
|
||||
# Define all the structures for CreateProcess
|
||||
Add-Type -TypeDefinition @"
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct PROCESS_INFORMATION
|
||||
{
|
||||
public IntPtr hProcess; public IntPtr hThread; public uint dwProcessId; public uint dwThreadId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct STARTUPINFO
|
||||
{
|
||||
public uint cb; public string lpReserved; public string lpDesktop; public string lpTitle;
|
||||
public uint dwX; public uint dwY; public uint dwXSize; public uint dwYSize; public uint dwXCountChars;
|
||||
public uint dwYCountChars; public uint dwFillAttribute; public uint dwFlags; public short wShowWindow;
|
||||
public short cbReserved2; public IntPtr lpReserved2; public IntPtr hStdInput; public IntPtr hStdOutput;
|
||||
public IntPtr hStdError;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SECURITY_ATTRIBUTES
|
||||
{
|
||||
public int length; public IntPtr lpSecurityDescriptor; public bool bInheritHandle;
|
||||
}
|
||||
|
||||
public static class Kernel32
|
||||
{
|
||||
[DllImport("kernel32.dll", SetLastError=true)]
|
||||
public static extern bool CreateProcess(
|
||||
string lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags,
|
||||
IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo,
|
||||
out PROCESS_INFORMATION lpProcessInformation);
|
||||
}
|
||||
"@
|
||||
|
||||
# StartupInfo Struct
|
||||
$StartupInfo = New-Object STARTUPINFO
|
||||
$StartupInfo.dwFlags = $StartF # StartupInfo.dwFlag
|
||||
$StartupInfo.wShowWindow = $ShowWindow # StartupInfo.ShowWindow
|
||||
$StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo) # Struct Size
|
||||
|
||||
# ProcessInfo Struct
|
||||
$ProcessInfo = New-Object PROCESS_INFORMATION
|
||||
|
||||
# SECURITY_ATTRIBUTES Struct (Process & Thread)
|
||||
$SecAttr = New-Object SECURITY_ATTRIBUTES
|
||||
$SecAttr.Length = [System.Runtime.InteropServices.Marshal]::SizeOf($SecAttr)
|
||||
|
||||
# CreateProcess --> lpCurrentDirectory
|
||||
$GetCurrentPath = (Get-Item -Path ".\" -Verbose).FullName
|
||||
|
||||
# Call CreateProcess
|
||||
[Kernel32]::CreateProcess($Binary, $Args, [ref] $SecAttr, [ref] $SecAttr, $false, $CreationFlags, [IntPtr]::Zero, $GetCurrentPath, [ref] $StartupInfo, [ref] $ProcessInfo) |out-null
|
||||
|
||||
echo "`nProcess Information:"
|
||||
Get-Process -Id $ProcessInfo.dwProcessId |ft
|
||||
}
|
||||
|
||||
if ($args.Length -eq 1) {
|
||||
if ($args[0] -eq 'install') {
|
||||
Install
|
||||
Exit(0)
|
||||
} elseif ($args[0] -eq 'find_browsers') {
|
||||
FindBrowsers | Format-List
|
||||
Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
$message = GetMessage
|
||||
if ($message -eq 'ping') {
|
||||
SendReply @{'version'='7.2.2';'file'=$PSCommandPath}
|
||||
} elseif ($message -eq 'find') {
|
||||
SendReply (FindBrowsers)
|
||||
} else {
|
||||
if ($message.Length -gt 1) {
|
||||
$c = $message.Length - 1
|
||||
Invoke-CreateProcess -Binary $message[0] -Args ('"' + $message[0] + '" ' + [String]::Join(' ', $message[1..$c])) -CreationFlags 0x01000010 -ShowWindow 1 -StartF 1
|
||||
} else {
|
||||
Invoke-CreateProcess -Binary $message[0] -CreationFlags 0x01000000 -ShowWindow 1 -StartF 1
|
||||
}
|
||||
SendReply $null
|
||||
}
|
164
native/download_with_windows.py
Normal file
|
@ -0,0 +1,164 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import struct
|
||||
import subprocess
|
||||
|
||||
VERSION = '7.2.6'
|
||||
|
||||
try:
|
||||
sys.stdin.buffer
|
||||
|
||||
# Python 3.x version
|
||||
# Read a message from stdin and decode it.
|
||||
def getMessage():
|
||||
rawLength = sys.stdin.buffer.read(4)
|
||||
if len(rawLength) == 0:
|
||||
sys.exit(0)
|
||||
messageLength = struct.unpack('@I', rawLength)[0]
|
||||
message = sys.stdin.buffer.read(messageLength).decode('utf-8')
|
||||
return json.loads(message)
|
||||
|
||||
# Send an encoded message to stdout
|
||||
def sendMessage(messageContent):
|
||||
encodedContent = json.dumps(messageContent).encode('utf-8')
|
||||
encodedLength = struct.pack('@I', len(encodedContent))
|
||||
|
||||
sys.stdout.buffer.write(encodedLength)
|
||||
sys.stdout.buffer.write(encodedContent)
|
||||
sys.stdout.buffer.flush()
|
||||
|
||||
except AttributeError:
|
||||
# Python 2.x version (if sys.stdin.buffer is not defined)
|
||||
print('Python 3.2 or newer is required.')
|
||||
sys.exit(-1)
|
||||
|
||||
|
||||
def install():
|
||||
import sys
|
||||
try:
|
||||
import winreg as _winreg
|
||||
except:
|
||||
import _winreg
|
||||
|
||||
this_file = os.path.realpath(__file__)
|
||||
install_path = os.path.dirname(this_file)
|
||||
|
||||
manifest = {
|
||||
'name': 'open_with',
|
||||
'description': 'Open With native host',
|
||||
'path': this_file,
|
||||
'type': 'stdio',
|
||||
}
|
||||
|
||||
manifest['path'] = filename = os.path.join(install_path, 'open_with.bat')
|
||||
with open(filename, 'w') as file:
|
||||
file.write('@echo off\r\ncall "%s" "%s" %%1 %%2\r\n' % (sys.executable, this_file))
|
||||
|
||||
registry_locations = {
|
||||
'chrome': os.path.join('Software', 'Google', 'Chrome', 'NativeMessagingHosts'),
|
||||
'chromium': os.path.join('Software', 'Chromium', 'NativeMessagingHosts'),
|
||||
'firefox': os.path.join('Software', 'Mozilla', 'NativeMessagingHosts'),
|
||||
'thunderbird': os.path.join('Software', 'Thunderbird', 'NativeMessagingHosts'),
|
||||
}
|
||||
|
||||
for browser, registry_location in registry_locations.items():
|
||||
browser_manifest = manifest.copy()
|
||||
if browser in ['firefox', 'thunderbird']:
|
||||
browser_manifest['allowed_extensions'] = ['openwith@darktrojan.net']
|
||||
else:
|
||||
browser_manifest['allowed_origins'] = [
|
||||
'chrome-extension://cogjlncmljjnjpbgppagklanlcbchlno/', # Chrome
|
||||
'chrome-extension://fbmcaggceafhobjkhnaakhgfmdaadhhg/', # Opera
|
||||
]
|
||||
|
||||
filename = os.path.join(install_path, 'open_with_%s.json' % browser)
|
||||
with open(filename, 'w') as file:
|
||||
file.write(
|
||||
json.dumps(browser_manifest, indent=2, separators=(',', ': '), sort_keys=True).replace(' ', '\t') + '\n'
|
||||
)
|
||||
|
||||
key = _winreg.CreateKey(_winreg.HKEY_CURRENT_USER, registry_location)
|
||||
_winreg.SetValue(key, 'open_with', _winreg.REG_SZ, filename)
|
||||
|
||||
|
||||
def find_browsers():
|
||||
try:
|
||||
import winreg as _winreg
|
||||
except:
|
||||
import _winreg
|
||||
|
||||
windir = os.getenv('windir')
|
||||
key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, os.path.join('Software', 'Clients', 'StartMenuInternet'))
|
||||
count = _winreg.QueryInfoKey(key)[0]
|
||||
|
||||
browsers = []
|
||||
found_msedge = False
|
||||
while count > 0:
|
||||
subkey = _winreg.EnumKey(key, count - 1)
|
||||
try:
|
||||
browsers.append({
|
||||
'name': _winreg.QueryValue(key, subkey),
|
||||
'command': _winreg.QueryValue(key, os.path.join(subkey, 'shell', 'open', 'command'))
|
||||
})
|
||||
if subkey == 'Microsoft Edge':
|
||||
found_msedge = True
|
||||
except:
|
||||
pass
|
||||
count -= 1
|
||||
|
||||
if not found_msedge and \
|
||||
os.path.exists(os.path.join(windir, 'SystemApps', 'Microsoft.MicrosoftEdge_8wekyb3d8bbwe', 'MicrosoftEdge.exe')):
|
||||
browsers.append({
|
||||
'name': 'Microsoft Edge',
|
||||
'command': os.path.join(windir, 'explorer.exe') + ' "microsoft-edge:%s "'
|
||||
})
|
||||
|
||||
return browsers
|
||||
|
||||
|
||||
def listen():
|
||||
receivedMessage = getMessage()
|
||||
if receivedMessage == 'ping':
|
||||
sendMessage({
|
||||
'version': VERSION,
|
||||
'file': os.path.realpath(__file__)
|
||||
})
|
||||
elif receivedMessage == 'find':
|
||||
sendMessage(find_browsers())
|
||||
else:
|
||||
for k, v in os.environ.items():
|
||||
if k.startswith('MOZ_'):
|
||||
try:
|
||||
os.unsetenv(k)
|
||||
except:
|
||||
os.environ[k] = ''
|
||||
|
||||
CREATE_BREAKAWAY_FROM_JOB = 0x01000000
|
||||
CREATE_NEW_CONSOLE = 0x00000010
|
||||
subprocess.Popen(receivedMessage, creationflags=CREATE_BREAKAWAY_FROM_JOB | CREATE_NEW_CONSOLE)
|
||||
sendMessage(None)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) == 2:
|
||||
if sys.argv[1] == 'install':
|
||||
install()
|
||||
sys.exit(0)
|
||||
elif sys.argv[1] == 'find_browsers':
|
||||
print(find_browsers())
|
||||
sys.exit(0)
|
||||
|
||||
allowed_extensions = [
|
||||
'openwith@darktrojan.net',
|
||||
'chrome-extension://cogjlncmljjnjpbgppagklanlcbchlno/',
|
||||
'chrome-extension://fbmcaggceafhobjkhnaakhgfmdaadhhg/',
|
||||
]
|
||||
for ae in allowed_extensions:
|
||||
if ae in sys.argv:
|
||||
listen()
|
||||
sys.exit(0)
|
||||
|
||||
print('This is the Open With native helper, version %s.' % VERSION)
|
||||
print('Run this script again with the word "install" after the file name to install.')
|
12
options.css
Normal file
|
@ -0,0 +1,12 @@
|
|||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
#group > div {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
margin: 4px;
|
||||
}
|
||||
#test_results, #exeinput {
|
||||
flex-grow: 1;
|
||||
}
|
27
options.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title data-message="options_title">Download With Options</title>
|
||||
<link rel="stylesheet" type="text/css" href="options.css" />
|
||||
<link rel="icon" type="image/png" href="images/16.png" />
|
||||
</head>
|
||||
<body>
|
||||
<center id=group>
|
||||
<div><img width=24 height=24 src='images/24.png'> <b>Download With</b><div style='flex-grow: 1;'></div>Options</div>
|
||||
<hr>
|
||||
<b>Native Test</b>
|
||||
<div id=test>
|
||||
<div id=test_results>Click button to test.</div>
|
||||
<button id=test_button data-message="test_button">Test</button>
|
||||
</div>
|
||||
<b>Executable</b>
|
||||
<div id=execute>
|
||||
<input id=exeinput type=text></div>
|
||||
</div>
|
||||
<div>Use '%s' in place of the URL.</div>
|
||||
</center>
|
||||
<script type="text/javascript" src="common.js"></script>
|
||||
<script type="text/javascript" src="options.js"></script>
|
||||
</body>
|
||||
</html>
|
35
options.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* globals chrome, compare_versions, compare_object_versions, get_version_warn, get_string, get_strings */
|
||||
let testResult = document.getElementById('test_results');
|
||||
let exeInput = document.getElementById('exeinput');
|
||||
|
||||
document.getElementById('test_button').onclick = function() {
|
||||
function error_listener() {
|
||||
testResult.style.color = 'red';
|
||||
testResult.innerText = "Error";
|
||||
}
|
||||
|
||||
let port = chrome.runtime.connectNative('download_with');
|
||||
port.onDisconnect.addListener(error_listener);
|
||||
port.onMessage.addListener(function(message) {
|
||||
if (message) {
|
||||
console.log(message);
|
||||
testResult.style.color = 'darkgreen';
|
||||
testResult.innerText = "Success!";
|
||||
} else {
|
||||
error_listener();
|
||||
}
|
||||
port.onDisconnect.removeListener(error_listener);
|
||||
port.disconnect();
|
||||
});
|
||||
port.postMessage('ping');
|
||||
};
|
||||
|
||||
|
||||
|
||||
exeInput.onchange = function(event) {
|
||||
chrome.storage.local.set({execute: exeInput.value});
|
||||
}
|
||||
|
||||
chrome.storage.local.get({execute: null}, function({execute}) {
|
||||
exeInput.value = execute;
|
||||
});
|