Is there a way to open mailto: and tel: links from a service worker?

Viewed 237

I'm using push notifications handled from a service worker.

The main motivation to use notifications was to provide actions as "Call to" or "Mail to", I though that the behaviour would be the same as clicking on a "mailto:" link.

It works using chrome on windows (launches mail app on click for example) but fails using chrome on android, resulting in a black tab with the url "mailto:..." written on it.

// Service Worker
self.addEventListener('notificationclick', function(event) {
  const { contactRequest } = JSON.parse(event.notification.data);
  switch(event.action) {
    case 'call':
      return clients.openWindow('tel:' + contactRequest.phone);
    case 'mail':
      return clients.openWindow('mailto:' + contactRequest.email);
  }
});
1 Answers

Updated with additional information

This seems to be a bug that manifests itself in many ways - Claimed to be fixed here for an unrelated origin - https://bugs.chromium.org/p/chromium/issues/detail?id=792990

There are not many options within the notification feature itself, you can only use a openWindow which creates or uses a window to perform additional options.

The issue faced in Chrome is acknowledged in MDN as well -https://developer.mozilla.org/en-US/docs/Web/API/Clients/openWindow

There are two approaches here

  1. Open or focus your application and add a hash which servers as a marker that the notification was clicked - this lets you add a target _top or _blank

Pseudo code with credit to MDN

// Notification click event listener
self.addEventListener('notificationclick', e => {
  // Close the notification popout
  e.notification.close();
  // Get all the Window clients
  e.waitUntil(clients.matchAll({ type: 'window' }).then(clientsArr => {
    // If a Window tab matching the targeted URL already exists, add a "#mailNotification"
    const hadWindowToFocus = clientsArr.some(windowClient => windowClient.url === e.notification.data.url ? (windowClient.navigate(e.notification.data.url+"#mailNotification").then(function(client){client.focus()}), true) : false);

// Add additional code to add a 
    // Otherwise, open a new tab to the applicable URL and focus it.
    if (!hadWindowToFocus) clients.openWindow(e.notification.data.url+"#mailNotification").then(windowClient => windowClient ? 
    windowClient.navigate(e.notification.data.url+"#mailNotification").then(function(client){client.focus()})
     : null);
  }));

// Then in your page, you can just use window.onhashChange event
window.onhashchange = weFixChromeLinks



function weFixChromeLinks () {

// ... Create an anchor tag that is formatted to your mailto has a target _top or _blank, hide the link and dispatch a click.
}
  1. Earlier Approach

Since the clients.openWindow method does not supply ability to target the _top window, you might have to set an intermediary page that supports a _top - i.e

// Your intermediate page 
window.open('mailto...','_top')

Closing words The issue itself is ugly - Browsers are supposed to know intents, e.g: Apps, mail programs etc. - It seems like Chrome for android treats it like another URL and fails miserably.

Related