Fork
This commit is contained in:
parent
924a8f1350
commit
61c0a11524
87
README.md
87
README.md
|
|
@ -1,12 +1,85 @@
|
|||
#Clipboard Inserter
|
||||
# Native Inserter
|
||||
|
||||
A simple addon whose purpose is to automatically insert contents of clipboard into the page.
|
||||
Fork of the Clipboard Inserter whose purpose it is to automatically insert the
|
||||
data received by an in this repository included native application into a
|
||||
broswer page.
|
||||
|
||||
If you're looking to install this addon, it's available here:
|
||||
It is useful for use with text extraction tools like Textractor for looking up
|
||||
words in the browser.
|
||||
|
||||
- [Firefox](https://addons.mozilla.org/firefox/addon/clipboard-inserter/)
|
||||
- [Chrome web store](https://chrome.google.com/webstore/detail/clipboard-inserter/deahejllghicakhplliloeheabddjajm)
|
||||
This repository contains the browser plugin, native application and native
|
||||
manifest. Textractor plugin is not included.
|
||||
|
||||
Or, if the links don't work, just search for "clipboard inserter" in the appropriate addon market.
|
||||
Currently this addon is not available on any of the browsers Addon Store.
|
||||
|
||||
On Chrome, if you want to use this extension with local files (the `file://` protocol), you have to enable the "Allow access to file URLs" setting in the extension details.
|
||||
Only tested on GNU/Linux with Firefox.
|
||||
|
||||
## Install
|
||||
|
||||
You will need:
|
||||
|
||||
- This code
|
||||
- A go compiler
|
||||
- A browser supporting native extensions (eg modern Firefox, Chrome)
|
||||
|
||||
1) Compile and install the native application
|
||||
2) Put the native application manifest into your browsers expected directory
|
||||
3) Install the addon in your browser
|
||||
|
||||
For this to be useful you will also need a sender, for example a Textractor
|
||||
plugin (not included) and a browser page that the can be inserted to.
|
||||
|
||||
## How does it work
|
||||
|
||||
The browser plugin starts a native application which creates a raw TCP listen
|
||||
socket for incoming connections.
|
||||
|
||||
One or more applications (eg Textractor plugin) will connect to this socket and
|
||||
send messages. Messages consist of a 4 Byte little-endian length header and
|
||||
UTF-8 payload.
|
||||
|
||||
The native application will forward the UTF-8 data to the browser plugin which
|
||||
in turn will insert the text into a webpage similar to the original clipboard
|
||||
version.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
The native application is writing to stderr. Browsers usually forward this to
|
||||
their default log.
|
||||
|
||||
The browser addon itself
|
||||
|
||||
## (Not so) FAQ
|
||||
|
||||
#### Why not the clipboard
|
||||
|
||||
Abusing the clipboard functionality to transfer data to the browser is ugly. It
|
||||
does also not work under Wayland which does not allow unfocused applications to
|
||||
access the clipboard.
|
||||
|
||||
(No opinion here whether the native application/messaging setup is more or less
|
||||
ugly than the clipboard approach)
|
||||
|
||||
It also has the bonus of working with VMs without setting up clipboard
|
||||
forwarding between host and guest.
|
||||
|
||||
#### Why a native application
|
||||
|
||||
The APIs including TCP listen sockets are no longer supported by modern
|
||||
Browsers. The only alternative would be connecting to a WebSocket server, but
|
||||
this has two drawbacks:
|
||||
|
||||
1) The API only supports the client side protocol and does not implement a
|
||||
server. This would mean the sending side would need to be the server and the
|
||||
native application the client, which would not work with multiple senders.
|
||||
|
||||
2) The sending side (eg C++ Textractor plugin) will need to implement a
|
||||
Websocket server which is a lot more work than raw tcp.
|
||||
|
||||
## Bugs
|
||||
|
||||
- Native messaging requires native host order prefixed messages. Golang does
|
||||
not have an easy way to retrieve this information. The native application
|
||||
will use little-endian which is the default on most common architectures
|
||||
- Messages over the native-messaging 1MB limit will be discarded instead of
|
||||
split up
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<script src="/default-options.js"></script>
|
||||
<script src="monitor.js"></script>
|
||||
</head>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
console.log("I'm alive")
|
||||
|
||||
let previousContent = ""
|
||||
let listeningTabs = []
|
||||
let timer = null
|
||||
let options = defaultOptions
|
||||
|
||||
chrome.storage.local.get(defaultOptions,
|
||||
o => options = o)
|
||||
|
||||
|
||||
chrome.storage.onChanged.addListener((changes, area) => {
|
||||
if(area === "local") {
|
||||
const optionKeys = Object.keys(options)
|
||||
|
|
@ -16,78 +15,45 @@ chrome.storage.onChanged.addListener((changes, area) => {
|
|||
options[key] = changes[key].newValue
|
||||
}
|
||||
}
|
||||
updateTimer()
|
||||
}
|
||||
})
|
||||
|
||||
chrome.browserAction.onClicked.addListener(() => {
|
||||
chrome.tabs.query({ active: true, currentWindow: true },
|
||||
([t]) => toggleTab(t.id))
|
||||
chrome.browserAction.onClicked.addListener((tab) => {
|
||||
toggleTab(tab.id)
|
||||
})
|
||||
|
||||
window.onload = () => {
|
||||
document.querySelector("#paste-target").addEventListener("paste", e => {
|
||||
if(e.clipboardData.getData("text/plain") === "") {
|
||||
e.preventDefault() // prevent anything that is not representable as plain text from being pasted
|
||||
napp = browser.runtime.connectNative("native_inserter")
|
||||
napp.onDisconnect.addListener((p) => {
|
||||
if (p.error) {
|
||||
console.error(`Disconnected native app due to an error: ${p.error.message}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
napp.onMessage.addListener((msg) => {
|
||||
console.log("Received: " + msg.body)
|
||||
const pasteTarget = document.querySelector("#paste-target")
|
||||
pasteTarget.innerText = msg.body
|
||||
const content = pasteTarget.innerText
|
||||
listeningTabs.forEach(id => notifyForeground(id, content))
|
||||
})
|
||||
|
||||
function toggleTab(id) {
|
||||
const index = listeningTabs.indexOf(id)
|
||||
if(index >= 0) {
|
||||
uninject(id)
|
||||
listeningTabs.splice(index, 1)
|
||||
updateTimer()
|
||||
chrome.browserAction.setBadgeText({ text: "", tabId: id })
|
||||
} else {
|
||||
chrome.tabs.executeScript({file: "/fg/insert.js"})
|
||||
listeningTabs.push(id)
|
||||
updateTimer()
|
||||
chrome.browserAction.setBadgeBackgroundColor({ color: "green", tabId: id })
|
||||
chrome.browserAction.setBadgeText({ text: "ON", tabId: id })
|
||||
}
|
||||
}
|
||||
|
||||
function notifyForeground(id, text) {
|
||||
chrome.tabs.sendMessage(id, {
|
||||
action: "insert", text, options
|
||||
})
|
||||
chrome.tabs.sendMessage(id, { action: "insert", text, options })
|
||||
}
|
||||
|
||||
function uninject(id) {
|
||||
chrome.tabs.sendMessage(id, { action: "uninject" })
|
||||
}
|
||||
|
||||
function checkClipboard() {
|
||||
const pasteTarget = document.querySelector("#paste-target")
|
||||
pasteTarget.innerText = ""
|
||||
pasteTarget.focus()
|
||||
document.execCommand("paste")
|
||||
const content = pasteTarget.innerText
|
||||
if(content.trim() !== previousContent.trim() && content != "") {
|
||||
listeningTabs.forEach(id => notifyForeground(id, content))
|
||||
previousContent = content
|
||||
}
|
||||
}
|
||||
|
||||
function updateTimer() {
|
||||
function stop() {
|
||||
clearInterval(timer.id)
|
||||
timer = null
|
||||
}
|
||||
function start() {
|
||||
const id = setInterval(checkClipboard, options.monitorInterval)
|
||||
timer = { id, interval: options.monitorInterval }
|
||||
}
|
||||
if(listeningTabs.length > 0) {
|
||||
if(timer === null) {
|
||||
start()
|
||||
} else if(timer.interval !== options.monitorInterval) {
|
||||
stop()
|
||||
start()
|
||||
}
|
||||
} else {
|
||||
stop()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,23 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Clipboard Inserter",
|
||||
"version": "0.3.2",
|
||||
"name": "Native Inserter",
|
||||
"version": "1.0.0",
|
||||
|
||||
"description": "A simple addon that inserts clipboard contents into the page. Uses icon made by Google from www.flaticon.com licensed by CC 3.0 BY",
|
||||
"description": "An addon that inserts contents received from a native application into a page. Forked from clipboard-inserter. Uses icon made by Google from www.flaticon.com licensed by CC 3.0 BY",
|
||||
|
||||
"icons": {},
|
||||
|
||||
"applications": {
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "@clipboard-inserter"
|
||||
"id": "@native-inserter",
|
||||
"strict_min_version": "50.0"
|
||||
}
|
||||
},
|
||||
|
||||
"permissions": [
|
||||
"activeTab",
|
||||
"clipboardRead",
|
||||
"storage",
|
||||
"nativeMessaging",
|
||||
"file://*/*"
|
||||
],
|
||||
|
||||
|
|
@ -27,7 +28,7 @@
|
|||
"32": "icon/icon32.png",
|
||||
"64": "icon/icon64.png"
|
||||
},
|
||||
"default_title": "Toggle clipboard inserter"
|
||||
"default_title": "Toggle Native Inserter"
|
||||
},
|
||||
|
||||
"background": {
|
||||
|
|
|
|||
Loading…
Reference in New Issue