Câmera (getUserMedia) trava indefinidamente ao debugar apps mobile no Service Studio/ODC Studio para
44
Views
1
Comments
New
Debugger

Câmera (getUserMedia) trava indefinidamente ao debugar apps mobile no Service Studio/ODC Studio para macOS — causa raiz: falta de entitlement de câmera no app

Produto / Componente

Service Studio para macOS / ODC Studio para macOS — Debug de aplicações mobile (alvo "Chrome (emulated)")

Ambiente

  • macOS: 27.0 (build 26A5378j)
  • Service Studio: 11.55.78.64991
  • ODC Studio: 1.7.14.10418
  • Chrome: 150.0.7871.115 (única instalação no sistema, sem Beta/Dev/Canary)
  • Máquina: MacBook pessoal (não gerenciada por MDM), câmera integrada (MacBook Pro Camera)

Resumo do problema

Ao iniciar uma sessão de debug no Service Studio/ODC Studio com o alvo "Chrome (emulated)", qualquer chamada a navigator.mediaDevices.getUserMedia() na página fica pendente para sempre — a Promise nunca resolve nem rejeita. Não aparece nenhum prompt de permissão de câmera, nenhum erro no console, e chrome://media-internals → aba "Players" nunca registra sessão de captura alguma (fica "No media player logs" indefinidamente).

O mesmo fluxo/URL funciona perfeitamente quando aberto manualmente em uma janela normal do Chrome (fora do Service Studio) — câmera abre e renderiza sem problemas.

Impacto

Não é possível debugar (breakpoints, inspeção de rede/console via Service Studio) nenhuma tela que dependa de câmera/getUserMedia — inclui fluxos de reconhecimento facial, liveness, upload de foto via captura direta, etc. — usando o Chrome (emulated) integrado ao Service Studio para macOS.

Passos para reproduzir

  1. Abrir um módulo mobile/reactive com uma tela que chama getUserMedia (ex.: captura de câmera para liveness).
  2. Na aba Debug Setup, com "Entry Module: (this module)" e browser "Chrome (emulated)" (única opção disponível), clicar em Start debugging.
  3. Navegar até a tela que solicita a câmera.
  4. Observar: nenhum prompt de permissão aparece; a tela fica travada (spinner/preto); nenhum erro no console.

Investigação já realizada (causa raiz identificada)

Passamos por um processo de eliminação completo antes de chegar à causa raiz — resumo dos testes:

  1. Verificado que getUserMedia é de fato chamado (interceptado via console) — a Promise fica em estado pending para sempre, sem resolver nem rejeitar.

  2. chrome://media-internals → Players: sempre vazio ("No media player logs") durante o travamento — a chamada nunca chega a criar uma sessão de captura rastreável.

  3. Descartado: constraints de câmera — constraints usadas (640x480 ideal) são suportadas pelo hardware (confirmado em chrome://media-internals → Video Capture: câmera enumerada corretamente via AV Foundation, múltiplas resoluções).

  4. Descartado: iframe / Permissions Policy — elemento de câmera não está em iframe.

  5. Descartado: perfil efêmero / modo Convidado (--bwsi) isoladamente — reproduzimos a linha de comando exata usada pelo Service Studio (capturada via ps aux durante uma sessão de debug ativa):

    /Applications/Google Chrome.app/Contents/MacOS/Google Chrome \  --remote-allow-origins=* --ignore-certificate-errors --no-default-browser-check \  --no-first-run --profile-directory=Default --bwsi --test-type \  --remote-debugging-port=9222 --user-data-dir=/ChromiumAdapterTemp/ \  --disable-search-engine-choice-screen 

    Ao lançar essa mesma linha de comando manualmente pelo Terminal (usuário, não Service Studio) — incluindo --bwsi, --remote-debugging-port (CDP) e perfil novo em $TMPDIR — a câmera funcionou normalmente em todos os testes isolados e combinados. Ou seja, nenhuma flag do Chrome usada pelo Service Studio é, por si só, a causa.

  6. Descartado: política/permissão de câmera — testamos inclusive forçar auto-concessão via política gerenciada do Chrome (VideoCaptureAllowedUrls, aplicada e confirmada em chrome://policy com status OK dentro da própria instância do Service Studio) — não teve efeito; media-internals continuou sem nenhuma sessão registrada.

  7. Causa raiz encontrada — falta de entitlement de câmera no processo pai: Inspecionamos a assinatura de código dos apps instalados:

    codesign -d --entitlements :- /Applications/ServiceStudio.appcodesign -d --entitlements :- "/Applications/ODC Studio.app"

    Resultado: nenhum dos dois declara NSCameraUsageDescription no Info.plist, e nenhum dos dois tem o entitlement com.apple.security.device.camera. Ambos rodam sob Hardened Runtime (com.apple.security.cs.allow-jit, allow-unsigned-executable-memory, allow-dyld-environment-variables), sem App Sandbox completo.

    Quando o Service Studio/ODC Studio lança o Chrome como processo filho para o debug ("Chrome (emulated)"), o macOS TCC (Transparency, Consent and Control) atribui a decisão de autorização de câmera ao processo responsável (o próprio Service Studio/ODC Studio, via o mecanismo de "responsible process"). Como esse app nunca declarou intenção de uso de câmera nem tem o entitlement correspondente, o TCC não tem como resolver o pedido do processo filho — não autoriza, não nega, não mostra prompt algum. A Promise do getUserMedia() fica pendente indefinidamente.

    Isso explica por que a mesma URL, com as mesmas flags de Chrome, funciona quando lançada pelo usuário (via Terminal ou Dock) — nesses casos o processo responsável não é o Service Studio, então não há a mesma lacuna de entitlement na cadeia.

Bundle IDs afetados

  • com.outsystems.servicestudio.launcher (ServiceStudio.app)
  • com.outsystems.odcstudio.launcher (ODC Studio.app)

Correção solicitada

Adicionar ao build macOS do Service Studio / ODC Studio:

  • NSCameraUsageDescription (e idealmente NSMicrophoneUsageDescription, caso fluxos de vídeo com áudio também sejam afetados) no Info.plist
  • O entitlement com.apple.security.device.camera (e com.apple.security.device.microphone se aplicável) na assinatura de código

para que o processo Chrome filho, lançado para debug ("Chrome (emulated)"), consiga negociar corretamente a autorização de câmera junto ao macOS TCC.

Workaround atual (client-side, sem alteração do produto)

Não há workaround dentro do Service Studio. Para continuar testando telas dependentes de câmera enquanto o fix não sai: usar "Chrome (emulated)" apenas para a lógica antes/depois da tela de câmera; para a tela em si, copiar a URL gerada pelo debug e abrir manualmente em uma janela de Chrome iniciada pelo próprio usuário (fora do Service Studio) — confirmado funcionando em todos os testes, mas perde a sincronia de breakpoints visuais do Service Studio nessa tela específica.

There is no 'translate' button on the ideas section, so if you want people to upvote your idea, maybe (also) post it in English