10

I am using Firebase Cloud Messaging (FCM) to send Data messages so that I can handle notification using Service Worker. Now I show the notification using Service Worker and when I click the notification I want to copy the content of notification in the clipboard.

const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler((payload)=> {
    const title = payload.data.title;
    const options = {
        body: payload.data.body
    };
    return self.registration.showNotification(title,
        options);
});

self.addEventListener('notificationclick', (event)=>{
    console.log(event);
    navigator.clipboard.writeText(event).then(function() {
        console.log('Async: Copying to clipboard was successful!');
      }, function(err) {
        console.error('Async: Could not copy text: ', err);
      });
});

When notification is clicked notificationclick event is fired. But I am getting navigator.clipboard as undefined. I am also using secured domain for my website. I am also not able to use document.execcommand('copy') because DOM is not accessible using Service Worker. Can you please suggest a way to copy notification content without opening any url?

Pawan Aichra
  • 371
  • 1
  • 13
  • I think you need this: https://developer.mozilla.org/en-US/docs/Web/API/Client/postMessage You will be able to do what you want in client side. Let me know if it helps you, I will made an anwser – Gilsdav May 23 '20 at 19:01
  • Seems like you have to open an actual browser window to run the copy command, otherwise you don't have access to that API. Maybe opening it, copying and closing can happen mostly like it never happened? I'd try to se how it goes even knowing it's not ideal. – enapupe May 23 '20 at 19:24
  • @Gilsdav as postMessage will work with DOM only, But l do not want to open any window. – Pawan Aichra May 23 '20 at 19:26
  • @enapupe yes, navigator.cilpborad will not work. But I am looking for some other way to achieve the same goal. – Pawan Aichra May 23 '20 at 19:28

2 Answers2

5

You cannot copy to clipboard from a ServiceWorker. You need an active foreground browser tab/window to copy to clipboard.

From chrome web updates archive https://developers.google.com/web/updates/2018/03/clipboardapi

As with many new APIs, navigator.clipboard is only supported for pages served over HTTPS. To help prevent abuse, clipboard access is only allowed when a page is the active tab. Pages in active tabs can write to the clipboard without requesting permission, but reading from the clipboard always requires permission.

I've also checked browser specs for both ServiceWorkers and Clipboard APIs and none defines anything specific about service workers context.

Edit: I've pinged the author of that post about this specific issue https://mobile.twitter.com/_developit/status/1264290519926128641

I don't believe it's available in service worker. My suggestion would be to have the notification click handler open a page if not already open, and call writeText() synchronously within that page when it received the event.

enapupe
  • 10,639
  • 3
  • 24
  • 41
2

You can use Client postMessage API:

Service worker :

self.addEventListener('notificationclick', (event)=>{
    console.log(event);

    if (!event.clientId) return;
    const client = await clients.get(event.clientId);
    if (!client) return;

    client.postMessage({
      type: 'clipboard',
      msg: event
    });
});

Simple script :

navigator.serviceWorker.addEventListener('message', event => {
  if(event.data.type === 'clipboard') {
      navigator.clipboard.writeText(event.data.msg).then(function() {
        console.log('Async: Copying to clipboard was successful!');
      }, function(err) {
        console.error('Async: Could not copy text: ', err);
      });
  }
});

Just keep in mind Safari does not support this feature.

Gilsdav
  • 982
  • 6
  • 10
  • As I have mentioned, I do not want to open a page. So how are we going to execute Simple script? – Pawan Aichra May 23 '20 at 19:15
  • I think you can open a window that only copy to clipbloard `clients.openWindow` and close itself directly after. https://developer.mozilla.org/en-US/docs/Web/API/Clients – Gilsdav May 23 '20 at 19:25