- Rohan Raja ([email protected])
Feature request: Async Clipboard: Add support for 'clipboardchange' event [41442253] - Chromium Spec: Clipboard API and events (w3.org)
- 1. Introduction
- 2. User scenarios
- 3. Motivation - Alternative to inefficient polling of clipboard
- 4. Proposed Approach
- 5 Alternatives considered
- 6 Appendix
- 7 Open issues
- 8 References & acknowledgements
The clipboardchange
event aims to provide an efficient and secure way of notifying web applications about changes to the system clipboard. This allows web applications to provide rich user experiences like dynamic contextual menu options based on available clipboard MIME types and ability to efficiently sync clipboard in web based virtual desktop clients.
Today, this can be achieved in Chromium by calling async clipboard read API in a polling approach (assuming clipboard-read permissions are granted) which is obviously inefficient. Also, polling is not feasible on Firefox and Safari as these browsers rely on combination of user activation and user gesture for reading clipboard through async API.
Hence clipboardchange
event is being proposed. This event will be fired, in a secure manner by firing only when document is in focus and requiring that clipboard contents are not part of this event.
Web-based editors like Word Online, Excel Online, Google Sheets, and similar applications support paste operations in multiple formats, such as CSV, images, HTML, and plain text. These editors may have separate paste functionality depending on the data type which is pasted, hence the web UI might have different paste buttons for each data type. The clipboard change event can be used to detect the change in available formats in clipboard and reflect the same on the UI as soon as it is changed.
Example scenario with clipboardchange event: Imagine a user working on a report in Word Online. They copy a table from Excel, which is available in multiple formats: plain text, HTML, and CSV. As soon as the user copies the table, the clipboardchange
event fires, and Word Online's UI updates to show buttons for "Paste as Text," "Paste as HTML," and "Paste as CSV." The user can then choose the most suitable format for their report with a single click, streamlining their workflow.
Scenario without clipboardchange event: If the user copies plain text then without clipboardchange notification, the web page would continue showing the "Paste as HTML" and "Paste as image" options. Clicking on "Paste as image" would require the web page to show some kind of error message. This unnecessary error scenario can be avoided by monitoring the clipboard and disabling the un-needed data type buttons upon clipboard change, which would prevent user clicking the invalid type button in the first place.
When a user copies text or an image on their local machine, a web-based remote desktop application can detect that clipboard contents have changed by listening for the clipboardchange
event. Upon detecting the change (which happens when 'clipboardchange' event is triggered on the web app when the page regains focus), the application can re-read the clipboard and send the updated clipboard content to the remote desktop environment.
Today, a web-app can monitor the system clipboard by polling and reading the clipboard through async clipboard API at regular intervals. However, polling is not efficient. Moreover, browsers like Firefox and Safari require user gesture for reading clipboard which makes polling infeasible in those browsers. This feature aims to introduce an efficient way of notifying web apps when clipboard changes which works in all browsers. Additionally we must ensure that we monitor the clipboard only when absolutely required, that is, there is at least one document having required permissions and is listening to the clipboard change event. This will be described in design details.
interface ClipboardChangeEvent : Event {
readonly attribute FrozenArray<DOMString> types;
};
// Event handler for clipboardchange event which contains the data types present in clipboard
function onClipboardChanged(event) {
document.getElementById("text_paste_button").disabled = !(event.types.includes('text/plain'));
document.getElementById("html_paste_button").disabled = !(event.types.includes('text/html'));
document.getElementById("png_paste_button").disabled = !(event.types.includes('img/png'));
}
navigator.clipboard.addEventListener("clipboardchange", onClipboardChanged);
A sample web application which demonstrates the usage of "clipboardchange" event for showing available paste formats for rich web editors Scenario 2.2 can be found here.
The ClipboardChange event object will have a types
member that lists all the available native formats available on the clipboard. Custom formats will not be included in this list.
interface ClipboardChangeEvent{
types: Array<string>; // MIME types available in the clipboard when the event was fired
}
The types
member can be used to detect available data types present on the clipboard and then reflect the same on the UI as per this scenario.
This API doesn't intend to provide any user clipboard contents as part of the event payload.
When fired, this API indicates that the clipboard has changed and provides the current MIME types present on the clipboard. Since the actual contents of the clipboard are not exposed, there is no need for user permissions.
1.) Simpler user experience with no permission prompts / user gesture requirements. 2.) Provides interop out of the box without need to implement new permissions.
The clipboardchange event will not fire if the target document is not focused. If clipboard changes occur while the document is not in focus, a single clipboardchange event will be fired when the document comes back into focus. Historical clipboard change information will not be available, only the available types when the page gained focus will be included in the types member.
Since the clipboardchange event is not triggered by a user action and the event is not associated to any DOM element, hence this event doesn't bubble up and is not cancellable.
This approach allows the clipboardchange event to be fired for a short duration after the user loses page focus, such as up to 5 seconds. This ensures that clipboard changes occurring immediately after focus loss are still captured, enhancing user experience without compromising security.
- Clipboard changes occurring immediately after the user loses focus are still captured, ensuring the web app can respond promptly when the user returns. Example: A web app can pre-process clipboard data while the user is in another application, reducing wait time when the user comes back.
- Limits the duration for which clipboard monitoring is allowed after focus loss, reducing the risk of prolonged unauthorized access.
- The short duration might not be sufficient for some use cases where clipboard changes occur after the specified time.
- Still requires monitoring for a brief period after focus loss, which could lead to resource usage if many pages implement this. Example: Multiple tabs monitoring clipboard changes for 5 seconds could still cause a temporary spike in resource usage.
The clipboardchange event can be considered a ClipboardEvent which includes a DataTransfer object as "clipboardData" property. This is similar to other clipboard related events like cut, copy or paste events. The clipboard types can be read using "clipboardData.types" property. However, methods to access actual clipboard data like "getData" won't be accessible. Calling these inaccessible methods would return an "undefined" or equivalent null value.
// Event handler for clipboardchange event which contains the data types present in clipboard
async function onClipboardChanged(event) {
const clipboardTypes = event.clipboardData.types;
document.getElementById("text_paste_button").disabled = !(clipboardTypes.includes('text/plain'));
}
navigator.clipboard.addEventListener("clipboardchange", onClipboardChanged);
One clear issue with this approach is that we are providing all the methods of DataTransfer API as part of this event even though only "types" property of DataTransfer is needed by this event.
OS | API |
---|---|
Windows | We can use the AddClipboardFormatListener function (winuser.h) which posts a WM_CLIPBOARDUPDATE message whenever the clipboard changes. |
MacOS | No API provided, need to poll OS clipboard for changes |
Linux | TBD |
ChromeOS | TBD |
Android / iOS | TBD |
Today browser engines have different approaches to clipboard API permissions. While Chromium has this permissions model for clipboard, Firefox and Safari rely on combination of user activation and user gesture for web pages to access user clipboard contents. This strict requirement is present because a user's clipboard contents are highly sensitive and can contain private data like passwords, security tokens.
To get the changed clipboard data within the event handler, the read or readText methods of the Async clipboard API can be used, given the web page has sufficient permissions. Note that in browsers which don't have permission based access to clipboard (like Firefox), a call to async clipboard read might require user gesture like clicking paste tablet. In those browsers, web authors can instead show a "Sync" button on the UI, which can be enabled upon receiving clipboardchange event and disabled again once user clicks the "Sync" button.
Custom clipboard data types are not part of this event because if custom MIME types are exposed (without user consent) a web page can know which applications a user is working on providing fingerprinting surface for malicious sites. Moreover, not all browsers support custom clipboard data types.
The clipboardchange event could be used as a communication channel between the host and the fencedframe, constituting a privacy threat. Hence the feasibility of this event within a fencedframe needs to be discussed.
Many thanks for valuable feedback and advice from:
- Luke Klimek ([email protected])
- Mike Jackson ([email protected])
- Prashant Nevase ([email protected])
- Rakesh Goulikar ([email protected])
- Sanket Joshi ([email protected])