Clipboard API [State of the Web]

Gepostet am: 02. August 2018

Standard web browsers allow developers to use the system clipboard. The Clipboard API is useful for customizing the copy/cut/paste actions. There are multiple scenarios, in which it makes sense to adapt the default behavior of these actions:

  • Reformatting the structure of the copied content
  • Attaching metadata or adding external data to the content
  • Copy/cut/paste on click (programmatic interface)
  • Explicitly set the Content-Type (MIME-Type)

This article is part of our State of the Web format we publish on a regular basis. Check out our other articles about the newest tech related stuff on the web.

How to use

There are two ways of dealing with the system clipboard. The first one, representing the currently most supported way is the Clipboard Event API, which lacks consistency and security. The second one is the upcoming way that aims to fix those issues.

  1. Clipboard Event API, based on clipboard events
  2. Asynchronous Clipboard API for extended programmatic use

Clipboard Event API

The Event API allows the developer to overwrite the default copy/cut/paste events by adding an event listener to the document and call the setData and getData method of the clipboard object. The examples in this article aim for the copy events.

To execute a clipboard event programmatically, document.execCommand can be used, which is supported by all standard web browsers. However, the functionality varies between browsers, as it can be seen in this “Can I use” Synchronous Clipboard API chart. “Synchronous” in this context means that the clipboard action must be initiated by the user manually, which is needed for several security reasons.

The code shows that additionally to the execCommand method, an eventListener for the copy event has to be set temporarily so that only the button click can overwrite the clipboards content.

A note about reading from the clipboard: Fortunately, the execCommand ('paste') is only supported by Internet Explorer. Other browsers only let the clipboard content be read by the application, if the user manually pastes something. See the next example:

Using the Clipboard Event API asynchronously

Clipboard Event API async

In case of asynchronously getting the data that should be copied into the clipboard after the user executed the copy request, browsers implemented timed conditions in order to ensure that the user intentionally wanted to do so. See this summary for detailed information.

External Library

To facilitate the functionality between browsers, the clipboard.js library was built. It works out of the box for all standard web browsers and has a simplified API for common clipboard use cases. What the clipboard.js library does internally is creating a fake textarea element, setting its values from the given text and making a selection on it, as seen in the code on GitHub. Having a focused, editable field on the DOM is a security feature from the past, which is still needed to be fulfilled as can be seen on “Can I use”. Clipboard.js meets all the various security conditions.

NEW Asynchronous Clipboard API

The current approach has several disadvantages regarding security for the user and ease of use for the developer:

  • The older Clipboard Event API which was discussed above is synchronous, so the clipboard transfer is blocking the whole page (this is especially bad when having large content, e.g. images)
  • Security issues like silently writing malicious content to the clipboard or reading sensitive data
  • Browser implementations of execCommand differ widely
  • Implementing a stable version working in all major browsers additionally requires the Selection API in order to create quite a weird code construct

In the W3C Editors Draft the proposed Asynchronous Clipboard API is documented. Since the end of April 2018, the first browser which supports initial parts of the new features is Chrome (v66 and up).

Mainly the new API contains

  • The navigator.clipboard object
  • Basic functionality for reading and writing clipboard data using promises
  • A clipboardchange event to globally detect clipboard changes

As with many new APIs, navigator.clipboard is only supported for pages served over localhost and HTTPS. Additionally, reading from the clipboard always requires permission, while writing to the clipboard can be handled without permission as long as the browser tab is active. The permissions can be manually configured in the Permissions API.

As can be seen in the code example above, one use case taking advantage of the new API is making a fetch request on a button click and copying the body content into the clipboard when loaded. With the new API, even long requests and other asynchronous function calls are working properly. Here is an example with copy to clipboard after a setTimeout. The clipboardchange event will be useful listening to for recognizing system clipboard changes.

The idea is, that a web application could also detect changes outside of the browser. If the user copies something from the system, the change event should fire as soon as the user comes back to the web app. There are still open controversial security discussions happening about this listener and to date the clipboardchange event is not supported by any browser!

Conclusion

Currently, the clipboard.js library is the most stable and and widely used method for accessing the clipboard from web browsers.

For the Asynchronous API,  there are still some open questions such as the fact that writing to the clipboard does not request any permission by default, which can result in really bad user experience should the clipboard content be overwritten by malicious data. For more information about potential abuse of the clipboard, read here.

The Editor’s Working Draft is pretty promising though, so that browsers other than Chrome (v66 and up) should support it in the near future. For all curios bleeding edge testers out there, the new API can be safely used with a conditional fallback implementation as explained on Stack Overflow by Dean Taylor, see this example code.

Ressources and further notes

2018-08-02T16:37:51+00:00