Browser clipboard access

From Trephine

Jump to: navigation, search
« Script onload piggybacking JavaScript copy to clipboard »

[subscribe] Recent blog entries

Live Demos

Browser clipboard access

Accessing the system clipboard is a notoriously difficult web problem. No major browser makes it easy, and only some even have APIs. Nevertheless, it is possible to access the system clipboard from the browser, given a sufficiently powerful plugin. This article shows you how.

Why use a plugin?

Unrestricted clipboard access would be a significant security concern (consider if you had credit card or password info in there), so it's understandable why browser makers take a hard line against programmatic clipboard access. Plugins, however, do not have to abide by the same security paradigms as the native browser.

In particular, signed Java applets have all the power of desktop Java, including access to the system clipboard. Trephine exposes this power to the web developer through a simple JavaScript API, which we'll use to read clipboard data.

Live demo

Without further ado, here's the executable JavaScript code:

// Setup steps to perform once trephine has loaded
var setup = function(){
  window.clipboard = {
    read: function() {
      var result = trephine.js( function() {
        var trans =
          java.awt.Toolkit.defaultToolkit.systemClipboard.getContents(null);
        var stringReader =
          trans.getTransferData(java.awt.datatransfer.DataFlavor.plainTextFlavor);
        var buf = new java.io.BufferedReader(stringReader), line, data = [];
        while ((line=buf.readLine())!=null) data[data.length] = line;
        return data.join("\n");
      } );
      if (result.error) throw result.error;
      return ( result.result ? result.result.toString() + '' : '' );
    }
  };
  alert('Setup complete! Now scroll down and try it out.');
};
 
// Load trephine, ask for privileges, then call setup()
trephine.load({
  onload: function() {
    trephine.askPermission( function(response) {
      if (response) setup(); 
      else alert("Sorry, you must grant privileges to access the clipboard.");
    } );
  }
});
< execute this code >

When you click the execute button at right, this code does the following:

  1. Loads trephine and prompts for elevated permissions,
  2. Creates a clipboard object with a read() function for extracting clipboard data.

Calling window.clipboard.read() will return any text in the system clipboard (if it contains text), or throws an exception on failure.

Here's an example to demonstrate:

try {
  var text = window.clipboard.read();
  alert('Clipboard text: ' + text);
} catch(err) {
  alert('Error reading text: ' + err.message);
}
< execute this code >

That's it!

How to use it in your code

Aside from the setup described above, you'll need to add trephine.js to your page as explained on the getting started page:

<script src="http://trephine.s3.amazonaws.com/trephine.js"></script>

If you don't want to include the <script> tag directly in the page, you can load it dynamically. Bespin trepanation has a good example of how to achieve this, using script onload piggybacking to automatically perform the setup steps after the script is loaded.

How it works

The key logic behind reading from the clipboard is this:

var result = trephine.js( function() {
  var trans =
    java.awt.Toolkit.defaultToolkit.systemClipboard.getContents(null);
  var stringReader =
    trans.getTransferData(java.awt.datatransfer.DataFlavor.plainTextFlavor);
  var buf = new java.io.BufferedReader(stringReader), line, data = [];
  while ((line=buf.readLine())!=null) data[data.length] = line;
  return data.join("\n");
} );

The above defines an anonymous function containing JavaScript code to execute in the privileged Rhino context. The privileged code does the following:

  1. Grabs a reference to the system Clipboard
  2. Asks the clipboard for its contents (returned as a Transferable)
  3. Creates a StringReader for extracting the clipboard data
  4. Iterates over the lines of clipboard text, appending them to a data array
  5. Concatenates the data array and returns the results.

The trephine.js() function attempts to execute this code, returning a result object containing information about the success of the operation, any error thrown, and the return value.

It is the responsibility of the calling code to handle this response object and take appropriate action. In this case, the read() function re-throws any error encountered or simply returns the result on success.

Future directions

If you found this useful, please leave a comment! If there's interest, I'll write a follow up article on how to write to the clipboard, or extract other types of data (such as image data).

Trephine is supported on many platforms. If you have trouble running the demo on this page, please leave a comment, making sure to specify your operating system, OS version, browser, browser version and Java plugin version (if known). Thanks in advance!

Explicit public domain declaration

Just so there's no confusion: all of the code snippets on this page are provided "AS IS", without warranty of any kind, express or implied.

All of the code snippets on this page are hereby released into the public domain by the me, the copyright holder. This applies worldwide. Or in case this is not legally possible: The copyright holder grants any entity the right to use this work for any purpose, without any conditions, unless such conditions are required by law.

If you'd feel better with a "real" license, you're free to use code snippets on this page under the MIT license as described on the about page.

Any links back to this site are always appreciated, but not required. Enjoy!

--Jim R. Wilson (jimbojw) 16:19, 24 March 2009 (UTC)