5

This question is related to another question I asked, but I realized that a side-question in that question deserved its own question.

Using JavaScript, I'd like to see what users are copying from a webpage. Reading clipboard content is fairly easy when the user is pasting:

document.addEventListener("paste", e => {
  let text = e.clipboardData.getData("text");
  alert("pasting text: " + text);
});

This correctly creates an alert with whatever was just pasted. However, getting clipboard data is more difficult when the user is copying.

Method 1 (doesn't work)

document.addEventListener("copy", e => {
  let text = e.clipboardData.getData("text");
  alert("copying text: " + text);
});

This alerts "copying data: " but with no text after it. That's because the getData method is returning "" (the empty string). My understanding is that it would be considered too much of a security problem for sites to read your clipboard when you're doing anything other than pasting.

Method 2 (works, but with a popup)

document.addEventListener("copy", () => {
  navigator.clipboard.readText().then(text => alert("copied text: " + text));
});

This works, but before alerting, it creates a popup asking for permission for the site to read the clipboard. I would prefer to not have this popup.

Method 3 (seems to work, but doesn't seem right)

document.addEventListener("copy", () => {
  let text = window.getSelection().toString();
  alert("copying text: " + text);
});

This appears to do what I want. It seems odd that this would be allowed, but Method 1 would not.

I have a couple of questions:

  1. Why is Method 1 not allowed, if Method 3 is? It seems like Method 1 could provide the same information as Method 3 does, and it would be more convenient and just as secure.
  2. Are there any cases where Method 3 would provide different results than Method 2 (in terms of the text variable, not popup behavior)?
  3. Are there any other downsides to using Method 3 that I'm not considering?

At this point, I only care about these answers in the context of Google Chrome or Chromium, not other browsers. Answers to any of these questions would be appreciated.

1
  • 1
    I think method one could get any information from your clipboard, also from other sites or programs, and method 3 can only get information from your site. Maybe that's why method one won't work. Didn't dig into documentation to check this out though, so I might be wrong. Commented Nov 3, 2018 at 17:31

2 Answers 2

2

tl;dr use Method 3 if you really think that not being honest with the user about what you're doing is justified- it's a good workaround, although many might consider it an exploit.

Looking at the W3 specification (https://www.w3.org/TR/clipboard-apis/#Cases) we can see some insight into why these events (and the still-developing API) exist in the first place. Specifically that copy is there for you to change what was copied in the case of your target not being what the user would actually want to end up on their clipboard, while paste exists to let you handle transfering that data into your application.

Knowing this, we can come to some conclusions:

  • Method 1: The spec does not go into much detail about clipboard security, except for making the intention that implementations should work to protect users. I'm not surprised, therefore, that the copied data is hidden from you; it seems like a sensible decision by the implementers. More than that, looking at the algorithms set-out by the spec, it's quite possible that there is not data in the clipboard yet, as the aim of this event is to allow you to set what should end up their.
  • Method 2: This seems much more the intention of the authors. If an application is going to access the clipboard, it should really get permission from the user. Especially because the clipboard might contain data from outside of your page.
  • Method 3: It's an exploit, but it's hard to see cases where it wouldn't work. From an implementer's perspective it's hard to block- as they would have to check event delegate functions for calls; compared to just 'not making the data readily available'. It's also, arguably, secure enough as the only information you can access is information that is already on your own document.
Sign up to request clarification or add additional context in comments.

Comments

1
const imageUrl = await navigator.clipboard.readText();
console.log(imageUrl);

You can also use Promise's .then() and .catch() if your code doesn't support async/await.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.