Conectar PWAs e IWAs com extensões do Chrome

Demián Renzulli
Demián Renzulli

Como desenvolvedor da Web, é uma prática recomendada projetar seus aplicativos usando o modelo de segurança de menor confiança possível, como um Progressive Web App (PWA). Essa abordagem maximiza seu alcance, minimiza o overhead de segurança que você precisa gerenciar e oferece a maior flexibilidade para desenvolvedores e usuários. No entanto, como a Web foi projetada para ser segura por padrão, o modelo de segurança conservador restringe naturalmente o acesso ao sistema operacional e a determinadas APIs de dispositivos avançadas.

Os Apps Isolados da Web (AIWs) resolvem esse problema fornecendo um modelo de aplicativo isolado, agrupado, com versão, assinado e altamente confiável criado na plataforma da Web. No entanto, antes de migrar para uma IWA, vale a pena considerar uma etapa mais gradual: conectar seu PWA a uma extensão do Chrome. Disponível em ambientes gerenciados do ChromeOS, como sessões de usuário gerenciadas, sessões de visitante gerenciadas (MGS, na sigla em inglês) ou modo quiosque, essa técnica permite que seu app use APIs de extensão de nível mais baixo por passagem de mensagens segura. O diagrama a seguir ilustra essa abordagem progressiva: começando com um aplicativo da web padrão, adicionando os recursos para se tornar um PWA instalável e, finalmente, explorando o caminho do PWA e da extensão do Chrome para desbloquear APIs adicionais.

imagem
O caminho de aprimoramento progressivo. Ao parear um PWA instalável com uma extensão complementar do Chrome, os desenvolvedores podem diminuir a distância entre o ambiente seguro da Web e os recursos de SO e dispositivos de nível inferior.

Se o aplicativo exigir recursos avançados que continuam indisponíveis mesmo com as APIs de extensão do Chrome, como Controlled Frame ou a API Direct Sockets, a melhor opção é migrar para um App Isolado da Web (IWA, na sigla em inglês). No entanto, embora os IWAs desbloqueiem novos recursos da Web avançados, talvez você ainda precise de APIs específicas no nível do dispositivo, exclusivas das extensões do Chrome, como chrome.runtime.restart() para reiniciar um dispositivo ChromeOS no modo quiosque. Felizmente, é possível conectar uma IWA a uma extensão do Chrome usando exatamente a mesma abordagem de um PWA. Essa técnica é abordada nas etapas a seguir.

Implementação detalhada

Implantar a extensão complementar

As extensões são implantadas pelo Admin Console do Chrome. Dependendo do ambiente de destino, configure isso na seção correspondente. Por exemplo, acesse Dispositivos > Chrome > Apps e extensões > Quiosques para o modo quiosque ou as guias respectivas para Usuários e navegadores ou Sessões de visitantes gerenciadas. Você pode hospedar a extensão por conta própria em um link acessível ao público ou diretamente na Chrome Web Store. Para instruções mais detalhadas sobre o gerenciamento de extensões, consulte a documentação oficial.

Implementar a transmissão de mensagens

Configuração da extensão

Para receber e responder a mensagens do seu web app, exponha um script em segundo plano que fique aguardando a chegada de mensagens do cliente (seu web app) e, em seguida, encaminhe essas solicitações para uma chamada de API correspondente. No exemplo a seguir, uma solicitação é encaminhada por proxy para reiniciar o dispositivo ChromeOS quando o app da Web envia um objeto de mensagem personalizada que contém um methodName de callRestart.

Background.js

// message handler - extension code
chrome.runtime.onMessageExternal.addListener(function (request, sender, sendResponse) {
  if (request.methodName == 'callRestart') {
    chrome.runtime.restart();
  }
});

O manifesto da extensão pode ser configurado para permitir chamadas de função externas à extensão usando a chave externally_connectable⁠⁠, que especifica quais sites e extensões podem chamar métodos na extensão. Mais informações sobre extensões do Chrome e o manifesto v3 podem ser encontradas na documentação oficial⁠⁠.

Se você estiver se conectando de um app da Web progressivo (PWA), liste o domínio HTTPS padrão em que o app está hospedado na matriz de correspondências. Confira um exemplo de manifesto configurado para um PWA em execução no modo quiosque:

Manifest.json

{
  "manifest_version": 3,
  "name": "Restart your kiosk app",
  "version": "1.0",
  "description": "This restarts your ChromeOS device.",
  "background": {
    "service_worker": "background.js"
  },
  "externally_connectable": {
    "accepts_tls_channel_id": false,
    "matches": [
      "*://developer.chrome.com/*"
    ]
  }
}

Se você estiver se conectando de um App Isolado da Web (IWA, na sigla em inglês), o mecanismo será exatamente o mesmo, mas o esquema de URL vai mudar. Como os AIWs são empacotados com segurança e não são executados em servidores da Web padrão, eles usam o próprio protocolo. É preciso adicionar a origem da IWA usando o esquema isolated-app://.

Manifest.json

{
  "manifest_version": 3,
  "name": "IWA Companion Extension",
  "version": "1.1",
  "description": "Companion extension for the IWA",
  "background": {
    "service_worker": "/scripts/background.js"
  },
  "externally_connectable": {
    "matches": [
      "isolated-app://*/*"
    ]
  }
}

Essa é a quantidade mínima de código necessária em uma extensão para detectar mensagens de uma PWA ou IWA.

Configuração de PWA e IWA

Para chamar a extensão de um app da Web, é necessário saber o ID estático dela. Esse ID pode ser encontrado na página chrome://extensions, que aparece quando você instala a extensão do Chrome, ou na Chrome Web Store depois que a extensão é enviada. Isso permite que o web app especifique a extensão exata com que se comunicar. Depois disso, chame chrome.runtime.sendMessage⁠⁠ e transmita o ID da extensão com uma mensagem para enviar a ela.

const STATIC_EXTENSION_ID = 'abcdefghijklmnopqrstuvwxyz';
// found from chrome extensions page of chrome web store.
const callExtensionAPI = function (method) {
  chrome.runtime.sendMessage(STATIC_EXTENSION_ID, {
    methodName: method,
  });
};
callExtensionAPI('callRestart');

Para mais informações sobre como conectar apps da Web a extensões para transmissão de mensagens, consulte a documentação de extensões⁠⁠.

Demonstração

Para conferir essa implementação em ação, acesse o repositório IWA Kitchen Sink (em inglês). Esse projeto serve como um playground abrangente para vários recursos de IWA, com demonstrações de APIs de alta confiança, como soquetes diretos e frames controlados. Ele também fornece um exemplo completo e funcional da conexão IWA-extensão do Chrome. O repositório inclui uma extensão complementar de exemplo e uma interface da Web dedicada que demonstra como usar a transmissão segura de mensagens para acionar métodos exclusivos da extensão. Por exemplo, você pode testar a busca das informações de perfil do usuário com a API chrome.identity.getProfileUserInfo() diretamente do App Isolado da Web.

Conclusão

Conectar seus aplicativos da Web a uma extensão do Chrome oferece um caminho seguro e progressivo para desbloquear recursos do dispositivo semelhantes aos nativos. Ao projetar a arquitetura do seu app, lembre-se destas principais conclusões:

  1. Comece com a Web:use um PWA por padrão para ter o melhor alcance e a menor sobrecarga de segurança.
  2. Preencha a lacuna com extensões:para recursos profundamente integrados no nível do SO (como reinicialização do dispositivo no modo quiosque), implante uma extensão complementar do Chrome e conecte-a ao seu aplicativo usando a transmissão segura de mensagens.
  3. Faça upgrade para IWAs somente se necessário:use Apps Isolados da Web quando precisar de APIs de alta confiança, como Direct Sockets, Controlled Frame ou qualquer outra API exclusiva de IWA.