Skip to content

Instantly share code, notes, and snippets.

@jinx1281255
Forked from LewdEwe-ErikWallace/clipboard.html
Created December 31, 2018 14:14
Show Gist options
  • Save jinx1281255/261d2649a06c69f61045c33eb240858e to your computer and use it in GitHub Desktop.
Save jinx1281255/261d2649a06c69f61045c33eb240858e to your computer and use it in GitHub Desktop.
This is an example of how to poll the clipboard for changes in an Electron application. See notes in HTML.
<!DOCTYPE html>
<html lang="en">
<head>
<title>My App - Clipboard</title>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' chrome-extension://*;">
</head>
<body>
<--
This is an example of how to poll the clipboard for changes in an Electron application.
In this example I'm monitoring the clipboard for the possibility of the user copying a login token -
identified by a prefix - from an email, and then I notify the rest of the app (not shown in this gist)
so the token can be pasted automatically into a login form.
The clipboard.js code creates a hidden Electron window containing this HTML, which is essentially an empty document.
It also does preload injection with preload_clipboard.js, which is what polls the clipboard every 250 ms.
The code is run in a separate window like this so it doesn't load the main Electron-Node process.
However, you could run the polling code anywhere that you can access the require('electron') object.
-->
</body>
</html>
"use strict";
// Import dependencies.
let electron = require('electron');
let emitter = require('events').EventEmitter;
let path = require('path');
let url = require('url');
// Constants.
const LOGIN_TOKEN_PREFIX = 'my-app:login-token#';
/*================================================================================================*/
/*································································································*/
/*
Constructor to create a clipboard instance and initialise its data.
*/
function Clipboard()
{
Object.defineProperty(this, 'window', {value: null, writable: true}); // The clipboard window.
// Setup event handlers for IPC messages.
electron.ipcMain.on('clipboard_message', this.ipc_message_handler.bind(this));
// Startup the database window.
this.create_window();
}
// Set the inheritance prototype of the constructor and name it.
Clipboard.prototype = Object.create(emitter.prototype, {constructor: {value: Clipboard}});
Clipboard.prototype.name = '<Clipboard>';
/*================================================================================================*/
/*································································································*/
/*
Save any data and close window.
*/
Clipboard.prototype.shutdown = function shutdown()
{
// Close the window.
this.window.close();
}
/*································································································*/
/*
Create the clipboard window.
*/
Clipboard.prototype.create_window = function create_window()
{
// Create the browser window.
this.window = new electron.BrowserWindow(
{
width: 0,
height: 0,
show: false,
webPreferences:
{
nodeIntegration: false,
preload: path.join(__dirname, 'preload_injectors', 'preload_clipboard.js'),
contextIsolation: true
}
}
);
// Load the base HTML of the application.
this.window.loadURL(url.format(
{
pathname: path.join(__dirname, 'clipboard', 'clipboard.html'),
protocol: 'file:',
slashes: true
}
));
// Open the Chrome Dev Tools.
// this.window.webContents.openDevTools();
// Setup window event handlers.
this.window.on('closed', this.window_closed.bind(this));
}
/*································································································*/
/*
Cleanup after the window is closed.
*/
Clipboard.prototype.window_closed = function window_closed()
{
// Dereference the window object.
this.window = null;
}
/*································································································*/
/*
Handle asynchronous clipboard messages coming in.
*/
Clipboard.prototype.ipc_message_handler = function ipc_message_handler(event, message)
{
switch(message.action)
{
case 'clipboard_changed':
if(message.value.indexOf(LOGIN_TOKEN_PREFIX) === 0)
{
// Notify rest of application that useful clipboard content was found.
this.emit('clipboard_login_token', message.value.substr(LOGIN_TOKEN_PREFIX.length));
}
break;
}
}
/*================================================================================================*/
module.exports = Clipboard;
"use strict";
let electron = require('electron');
let last_value = null;
/*================================================================================================*/
/*································································································*/
function post_ipc_message(message)
{
electron.ipcRenderer.send('clipboard_message', message);
}
/*································································································*/
/*
Normally the listener would take the form: function listener(event, message){}.
However, because our windows are sandboxed the event parameter is dropped and all we get
is the message parameter, so the listener needs to be: function listener(message){}.
*/
function add_ipc_message_listener(listener)
{
electron.ipcRenderer.on('ipc_message', listener);
}
/*································································································*/
function remove_ipc_message_listener(listener)
{
electron.ipcRenderer.removeListener('ipc_message', listener);
}
/*================================================================================================*/
function check_clipboard_for_changes()
{
let value = electron.clipboard.readText();
if(last_value !== value)clipboard_changed(value);
}
function clipboard_changed(value)
{
last_value = value;
post_ipc_message({action: 'clipboard_changed', value: value});
}
// Get the initial value of the clipboard.
clipboard_changed(electron.clipboard.readText());
// Check for changes at an interval.
setInterval(check_clipboard_for_changes, 250);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment