33

I want to be able to initiate real paste event when user clicks. I can understand this may be a security issue, because if any webpage had access to users clipboard, that would be bad. So I thought all browsers disallow accessing clipboard data.

But for example in google docs (in the word-like application), I can Paste from custom context menu (right mouse click on a html element pretending to be a context menu), even if the clipboard data has been copied to clipboard in different application like Microsoft Paint. This works in Google Chrome browser, which is the browser of my interest.

I thought they do it using flash, but it still works even if I completely disable flash in chrome. There was a question about this already, but the answer mentioned there is not correct. Another answer of that question suggests that google is using a chrome extension for this, but it still works even if I disable all extensions in chrome.

How to reproduce in windows:

  • disable flash in chrome, disable all extensions
  • restart
  • go to google docs and open new empty writing document (Docs, not spreadsheet)
  • run microsoft paint application in windows
  • draw something in microsoft paint, press Ctrl+A to select all, Ctrl+C to copy
  • switch back to chrome to the docs empty page, and rightclick the empty page
  • select Paste from the artificial context menu (notice the context menu is not the native menu from windows, but it comes from the html webpage of google docs)
  • you will see that the clipboard image was pasted to the docs document (!)
  • how do they do this?

I know how to access the clipboard data if user presses Ctrl+V on my webpage, because this triggers Paste event on the current window. But, how do I either access the clipboard data or initiate the paste of actual clipboard data (eg. a bitmap copied in mspaint) in javascript (or using jquery) while user just clicks a button or div?

Community
  • 1
  • 1
Tomas M
  • 6,919
  • 6
  • 27
  • 33
  • in html5 add attribute contenteditable="true" to div or any container element, then try it without any javascript – Suhail Keyjani Dec 26 '15 at 10:05
  • This apparently works for Ctrl+V, or using native context menu Paste event. But I am talking here about something else - pasting on mouse click, when mouse clicks some div or button. – Tomas M Dec 26 '15 at 10:06
  • Take a look at this article http://www.htmlgoodies.com/html5/other/working-with-clipboard-apis-in-html5-web-apps.html – jcubic Dec 26 '15 at 10:23
  • Thanks, that does not help, unfortunately. There is only described how to fire custom paste events (and comments mention it doesn't work at all). – Tomas M Dec 26 '15 at 10:31

3 Answers3

12

I want to be able to initiate real paste event when user clicks. I can understand this may be a security issue, because ...

The above is the bottom line..

Having this code JS Fiddle

var Copy =  document.getElementById('copy'),
    Cut =  document.getElementById('cut'),
    Paste =  document.getElementById('paste');

// Checking Clipboard API without an action from the user
console.log('Copy:' + document.queryCommandSupported('copy'));
console.log('Cut:' + document.queryCommandSupported('cut'));
console.log('Paste:' + document.queryCommandSupported('paste'));


//Now checking the clipboard API upon a user action
Copy.addEventListener('click', function(){
    console.log('Copy:' + document.queryCommandSupported('copy'));
});

Cut.addEventListener('click', function(){
    console.log('Cut:' + document.queryCommandSupported('cut'));
});

Paste.addEventListener('click', function(){
    console.log('Paste:' + document.queryCommandSupported('paste'));
});
<button id="copy">Copy</button>
<button id="cut">Cut</button>
<button id="paste">Paste</button>

If you check it with different browsers you'll see how browsers react differently dealing with the Clipboard API using queryCommandSupported() the result is:

Chrome 47:

  • Without user action, Copy:false , Cut:false , Past:false
  • With user action, Copy:true , Cut:true , Paste:false

Firefox 43:

  • Without user action, Copy:true , Cut:true , Past:false
  • With user action, Copy:true , Cut:true , Paste:false

IE11: - I believe it's same in Edge

  • Without user action, Copy:true , Cut:true , Past:true
  • With user action, Copy:true , Cut:true , Paste:true
  • While all options are true, IE asks the user for permission on all above actions.

Safari: - same for iOS Safari

  • Only fires copy event on a valid selection and only cut and paste in focused editable fields.
  • Only OS clipboard reading/writing via shortcut keys, not through document.execCommand().

For detailed browsers support for Clipboard API caniuse.com/#search=clip

Also browsers support paste using right-click context menu for conteneditable="true" elements as in this JS Fiddle 2


But for example in google docs (in the word-like application), I can Paste from custom context menu (right mouse click on a html element pretending to be a context menu), even if the clipboard data has been copied to clipboard in different application like Microsoft Paint.

I thought they do it using flash, but it still works even if I completely disable flash in chrome.

From Google Apps Script documentation for developing add-ons for Google Apps:
"The Platform: Apps Script's code editor is a web app that you launch from within Google Sheets, Docs, or Forms. The language is based on JavaScript, but executes on Google's servers rather than directly in the user's browser (with the exception of client-side user interfaces...".

Since it is being executed on their servers, I think they can enable certain features, or even use Java, for better experience.


EDIT 1:
If you check clipboard.js, you'll see the library doesn't have an option for "paste", only "copy" and "cut", also in the "Browser Support" section at the end of the page you'll see that the library relies on execCommand API, and doesn't work in Safari.


EDIT 2:
Upon an update of the question as well as comments, for the Google docs part, I pressed Prt Sc to have a screen-shot in the clipboard, opened Google docs in Chrome, right-clicked then clicked on "Paste" from the custom context menu and for sure it works, opened Google docs in Firefox and as soon I clicked on "paste" option I got this response

enter image description here

Also for the record, I tried to do the same in IE11 and it is still trying to launch Google docs since 21 minutes.

So the conclusion is probably, and mostly, "Google" Chrome has an Exception: - something like a conditional statement - for "Google" docs and other Google services in their browser, also I think @julien-gregoire was right about its being an extension in Firefox.

From this Google docs support page:

For security reasons, most browsers don't allow web apps like Docs, Sheets, and Slides to use your computer's clipboard through menus.

However, if you use Chrome, you can give permission to access your clipboard by installing the Google Drive Chrome app. This allows you to use the right-click menu to copy and paste content (or select "Copy" or "Paste" from the Edit menu in the toolbar). To install the app, visit the Chrome Web Store.

And this smallbusiness page:

Without keyboard shortcuts, you have two more options for copying and pasting: either going to the "Edit" menu and selecting "Copy" or "Paste," or right-clicking in the document and selecting either "Copy" or "Paste" from the context menu. In Google Docs, both these options are only available to Chrome users who have the Google Drive Web app installed. The app is free, but is not available for other browsers.

So seems they have already implemented that app as built-in feature in newer versions of Chrome.

inker
  • 325
  • 8
  • 15
Mi-Creativity
  • 9,554
  • 10
  • 38
  • 47
  • If you open an empty google document (writing app), then you open MS Paint, draw something, ctrl+a ctrl+C, then you go back to google document and rightclick the empty page, select Paste from the artificial context menu, and it pastes the actual mspaint data. No extension needed. I have all extensions disabled, still works. – Tomas M Dec 26 '15 at 18:52
  • @TomasM, I didn't say anything about extensions, but from their app script documentation - *the link is in the answer* - they say it is javascript based implementation *but* it get executed on their servers, all of it except for the user interface, so they can enable specific features, or use Java or C – Mi-Creativity Dec 26 '15 at 18:57
  • 2
    JavaScript based implementation of accessing WINDOWS CLIPBOARD from my computer CANNOT in any way run on their servers. This is entirely wrong. – Tomas M Dec 26 '15 at 18:58
  • Ok, got it not, tell me what browser you checking it with? – Mi-Creativity Dec 26 '15 at 19:04
  • it is Chrome!! their browser, I did the same in FIrefox, right-clicked, clicked on "`paste`" and I got this result immediately http://i.imgur.com/d0Z6xFS.png , tried to open Google docs in IE11 and it is still haven't loaded, it only works on Chrome, they made an exception for *Google* Docs in *Google* Chrome – Mi-Creativity Dec 26 '15 at 19:10
  • Thank you for digging into it. I probably forgot to mention that the only browser of my interest is google chrome. – Tomas M Dec 26 '15 at 20:32
  • You welcome, and same here, I only use other browsers for cross-browser testing – Mi-Creativity Dec 26 '15 at 20:35
  • The main question still remains: how do they do it? (how do the google docs developers do the trick with pasting of mspaint data in docs document on mouse click?). I would be very surprised to find out that google chrome only allows this only for their own site (eg. docs.google.com) – Tomas M Dec 26 '15 at 20:40
  • They've added it as an "*Exception*" in their browser engine when they programmed it, just to simply trying it, presume they have an array of exceptions like: `$expArr = [ 'google docs' , 'gmail' , 'google code', ... other google services]`, and a dummy switch-case or if statement `if($name.inArray($expArr){ enable document.execCommand('paste'); }` so when you on google docs appsor gmail the condition will met and you can paste, but for other websites you need to enable it manually in Chrome – Mi-Creativity Dec 26 '15 at 20:59
  • Well that would be indeed possibility. But is it only your guess? What is your source of such information? – Tomas M Dec 26 '15 at 21:01
  • 1st: because IMHO that's the only possible way to do it, 2nd: from this link https://support.google.com/docs/answer/161768?hl=en "`For security reasons, most browsers don't allow web apps like Docs, Sheets, and Slides to use your computer's clipboard through menus. However, if you use Chrome ..`" – Mi-Creativity Dec 26 '15 at 21:08
  • 3rd: this link http://smallbusiness.chron.com/copy-paste-google-docs-not-working-53088.html "`...or right-clicking in the document and selecting either "Copy" or "Paste" from the context menu. In Google Docs, both these options are only available to Chrome users who have the Google Drive Web app installed. The app is free, ` ***`but is not available for other browsers`***" – Mi-Creativity Dec 26 '15 at 21:09
6

Custom paste works in Chrome, but only through an extension. If you look at google docs code, you'll see that without the extension installed, you can't paste. And you can try in Firefox to use the context menu paste, it'll tell you it's not available, and that you need to use CTRL+V. You can find this in google docs source code:

Copying and pasting requires the free Google Drive web app. This lets us access your clipboard so you can cut, copy and paste.

So it seems clear that the paste command needs an extension to work.

One way to do it is to use execCommand('paste') which doesn't work when called from a page, but actually works in an extension content script. You only need to add clipboardRead to the manifest.json permissions, like this:

permissions: {
    ...
    "clipboardRead"
    ...
}

Then in your content script document.execCommand('paste') will work.

EDIT:

As pointed by @tomas-M and @Mi-Creativity, the implementation in google docs on Chrome seems to be in Chrome itself, not in an exposed extension. Maybe this can give a clue as to where it is defined: https://code.google.com/p/chromium/codesearch#chromium/src/chrome/common/extensions/api/_permission_features.json&q=clipboardRead&sq=package:chromium&dr=C&l=164

Hard to say if it's really the way it works, but in any case, you can 'unlock' execCommand('paste') for other site through an extension. Not very practical, but it works.

And testing document.execCommand('paste') in console, while on google docs gives true, while on other pages it gives false, so I really think that it's how this feature is implemented in google docs.

Mi-Creativity
  • 9,554
  • 10
  • 38
  • 47
Julien Grégoire
  • 16,864
  • 4
  • 32
  • 57
  • I've disabled all extensions, but it still works for me in Chrome. – Tomas M Dec 26 '15 at 18:53
  • @JulienGregoire you were right about it in Firefox but in Chrome it's not an extension it seems more like an exception for their Google docs, UpVoted – Mi-Creativity Dec 26 '15 at 19:40
  • "*And testing `document.execCommand('paste')` in console, while on google docs gives true, while on other pages it gives false...*" Hooray, just another proof it is an implemented Exception, brilliant – Mi-Creativity Dec 26 '15 at 21:28
  • That would mean, that anybody using Chrome browser is in a risk that his secret information stored in his clipboard can be accessed ANY TIME by google! – Tomas M Dec 28 '15 at 18:38
  • Yep, the clipboardRead permission gives access to your clipboard. No need even for a user action, or for the tab to be in focus to be allowed. It can be called as long as the page is opened. This is the same behavior when access is given through an extension or through this app exception. – Julien Grégoire Dec 28 '15 at 23:45
1

It works differently with different browsers. You can find a working implementation here: https://jsfiddle.net/1vmansr2/

Relevant JS:

function myFunction() {

   navigator.clipboard.readText()
.then(text => {
document.getElementById("demo").innerHTML = text;

})
.catch(err => {
document.getElementById("demo").innerHTML = 'Failed to read clipboard contents: '+err;
});


}
Anthony
  • 13,434
  • 14
  • 60
  • 80