Pdf.js: Erro: permissão negada para acessar a propriedade 'imprimir'

Criado em 23 nov. 2018  ·  39Comentários  ·  Fonte: mozilla/pdf.js

Configuração:

  • Navegador da Web e sua versão: todas as versões do Firefox desde que PDF.js foi incluído (5+ anos)
  • Sistema operacional e sua versão: todos
  • Versão PDF.js: todos
  • É uma extensão do navegador: n / a

Etapas para reproduzir o problema:

  1. https://bugzilla.mozilla.org/show_bug.cgi?id=911444

Qual é o comportamento esperado?
Que o PDF pode ser impresso como em qualquer outro navegador além do Firefox

O que deu errado?
Error: Permission denied to access property 'print'

Corrija isso, pois a solução de impressão universal de PDF no navegador está quebrada há 5 anos no Firefox desde que o pdf.js foi incluído no Firefox.

A comunidade de desenvolvedores da web tem centenas de soluções ruins para isso, por causa de um único projeto, pdf.js.

4-printing

Comentários muito úteis

@dotnetCarpenter a cereja do bolo é que, há mais de um ano, um dos desenvolvedores reclamou que todos os comentários do +1 tornam mais difícil ver a discussão técnica e, portanto, mais difícil resolver o bug. Como se fosse por isso que está aberto há mais de 6 anos. Sem o sistema de votação, esses comentários são agora a ÚNICA maneira de chamar a atenção para um problema, por isso não vejo alternativa.

Todos 39 comentários

Semelhante a https://github.com/mozilla/pdf.js/issues/5397 , mas não importa se você usa um iframe ou não.

Mesmo problema se estiver usando <object>

<object type="application/pdf"
    data="/media/examples/In-CC0.pdf"
    width="250"
    height="200">
</object>

Etapas para reproduzir o problema:

1. https://bugzilla.mozilla.org/show_bug.cgi?id=911444#c53

Por que abrir um problema duplicado aqui, quando isso já está claramente rastreado no Bugzilla !?
Especialmente porque isso não é nem mesmo um bug na biblioteca (geral) PDF.js em si, mas sim uma limitação no navegador Firefox (conforme descrito no bug vinculado, e uma correção, portanto, não aconteceria neste repositório de qualquer maneira).

@Snuffleupagus Porque o bug do Firefox foi relatado 5 anos atrás e a causa raiz é o pdf.js e não o Firefox. Nenhum desenvolvedor do Firefox tocou nisso e eu esbarrei nesse problema várias vezes e ele só pode ser resolvido alterando o pdf.js, não o Firefox.

Para esclarecer, a forma como o pdf.js funciona é que o normal (15+ anos) de impressão de um documento, print() , neste caso um PDF, está gerando um erro quando o

Posso estar errado ao dizer que o erro é realmente como o pdf.js é incorporado ao Firefox. Mas presumo que o pdf.js poderia escutar print() mais facilidade e usar sua lógica interna para imprimir o documento PDF.

window.onbeforeprint = function() {
    console.log('This will be called before the user prints.');
};
window.onafterprint = function() {
    console.log('This will be called after the user prints');   
};

Deve funcionar desde o Firefox 6

window.matchMedia('print') provavelmente não funcionará, pois o bug https://bugzilla.mozilla.org/show_bug.cgi?id=774398 não foi marcado como corrigido ou resolvido.

Esta é uma duplicata de # 5397 - a causa raiz do problema é que o pdf.js está embutido em um documento com uma entidade de segurança "

@Snuffleupagus é a pasta da web que faz parte do pacote pdf.js que está embutido no Firefox?
A única lógica de impressão que encontrei está em https://github.com/mozilla/pdf.js/blob/master/web/firefox_print_service.js

O principal problema com # 5397 é que ele trata metade da impressão ao usar pdf.js e metade de como imprimir um documento no Firefox quando o pdf.js está renderizando o documento, como neste tíquete. @automatedbugreportingfacility você está certo, mas achei que isso requer um novo problema, pois o número 5397 está turvando as águas.

A alteração do URI deve acontecer em https://bugzilla.mozilla.org/show_bug.cgi?id=911444#c53, mas em vez de uma correção no Firefox (não acontece há 5 anos), uma solução alternativa seria ouvir para o evento beforeprint e comece a imprimir via pdf.js. Se beforeprint for bloqueado pelo Firefox, devido à política de segurança de mesma origem, isso só pode acontecer no Firefox.
Talvez um de vocês possa esclarecer o assunto?

uma solução alternativa seria ouvir o evento beforeprint e começar a imprimir via pdf.js.

Você pode esclarecer? Para que o evento beforeprint seja enviado a um documento pdf.js incorporado, você precisa invocar print() no contexto de uma janela pai. O navegador imprimirá o conteúdo da janela principal. Você não pode "começar a imprimir" no manipulador de eventos, porque ele já começou a imprimir o documento pai.

Uma possível solução alternativa no lado do pdf.js seria implementar um manipulador onmessage para permitir a impressão por meio de pdfWindow.postMessage("print"); , mas não tenho certeza se é a solução desejada.

Uma possível solução alternativa no lado do pdf.js seria implementar um manipulador onmessage para permitir a impressão por meio de pdfWindow.postMessage ("print") ;, mas não tenho certeza se é a solução desejada.

@automatedbugreportingfacility uf, não, isso não é nem um pouco desejável. A solução perfeita seria ter paridade de API DOM com todos os outros navegadores, onde você pode usar .print() no contêiner de documento PDF.

Não criei esse problema porque uso pdf.js, mas porque o Firefox usa pdf.js e print() não funcionou desde que o pdf.js se tornou o padrão para renderizar PDFs no Firefox.

Ficarei feliz se isso for corrigido no Firefox e não no pdf.js ou vice-versa - de qualquer forma ficarei feliz 😃

então só pode acontecer no Firefox.
Talvez um de vocês possa esclarecer o assunto?

Já declaro em https://github.com/mozilla/pdf.js/issues/10290#issuecomment -441132851 que não é relevante para este repositório e https://github.com/mozilla/pdf.js/issues/ 10290 # issuecomment -441202543 descreve (com alguns detalhes) por que

Para tocar em .print sem que seja lançado um erro de segurança, é necessária uma correção para a situação resource://pdf.js que descrevi acima, e isso seria feito no Firefox. Podemos resolver esse problema, pois não há trabalho em pdf.js a fazer aqui e o bug do upstream está espelhado em # 5397.

@Snuffleupagus e @automatedbugreportingfacility apenas para ter certeza de que entendi o que você está dizendo.

Não há como criar uma política de segurança alternativa do Firefox em pdf.js, quando print() é chamado.

O acima está correto?

Sim, você não pode abrir um buraco nos mecanismos de segurança do navegador. Incorporar pdf.js em um documento semi-privilegiado foi um grande erro em primeiro lugar, mas não há como voltar atrás, e a Mozilla infelizmente prefere gastar dinheiro em coisas efêmeras como "Projeto Mortar". Mas estou divagando.

O experimento do Mortar foi concluído. A Mozilla não considera que o caso de uso de PDF justifica o fardo de implementar e manter o PDFium e uma implementação da API Pepper no Gecko.

Bem, pelo menos o Motar foi descontinuado .

Esse problema poderia definitivamente ser resolvido, mas antes que eu (você) o faça, já que tenho 2 especialistas em pdf.js aqui, tenho duas perguntas que possivelmente podem ajudar https://bugzilla.mozilla.org/show_bug.cgi?id=911444 a seguir na direção certa.

  1. Como o pdf.js deve ser incorporado ao Firefox, se não como um documento especial (_resource: // protocol_)?
  2. Qual é o layout de impressão em papel quando o Firefox imprime pdf.js, barras de ferramentas etc?

Incorporar pdf.js em um documento semi-privilegiado foi um grande erro em primeiro lugar, mas não há como voltar atrás

@automatedbugreportingfacility Por que essa decisão é irreversível?

Você não poderia simplesmente criar um novo documento em branco com pdf.js e a mesma origem da janela pai e alimentar o arquivo PDF em pdf.js?

<iframe id="pdf" src="some-same-origin.pdf"></iframe>
<script>
  document.getElementById('pdf').print()
</script>

Pontos de bônus, se o pdf.js ouvir beforeprint , cancele o evento e imprima o <canvas> (documento PDF) e não deixe o FIrefox imprimir a IU do pdf.js.

Imagino que, se o pdf.js fosse incorporado como um documento normal, você seria capaz de ouvir a janela pai.

window.opener.addEventListener('beforeprint', event => {
  event.preventDefault()

  window.print() // pdf.js overrides the native print function already
})

Ou mude o pdf.js para:

let print = (window.opener || window).print;
window.print = function print() {
  if (activeService) {
    console.warn('Ignored window.print() because of a pending print job.');
    return;
  }
  ...

Pensando bem, isso significaria que o pdf.js engoliria as impressões do pai, o que não é o que queremos.

Na verdade, o pdf.js já está fazendo a coisa certa. Precisamos apenas do firefox para enviar print() no documento que incorpora o pdf.js.

Trecho de _pdf_print_service.js_ (encontrado em https://mozilla.github.io/pdf.js/web/viewer.html):

let print = window.print;
window.print = function print() {
  if (activeService) {
    console.warn('Ignored window.print() because of a pending print job.');
    return;
  }
  ensureOverlay().then(function() {
    if (activeService) {
      overlayManager.open('printServiceOverlay');
    }
  });

  try {
    dispatchEvent('beforeprint');
  } finally {
    if (!activeService) {
      console.error('Expected print service to be initialized.');
      ensureOverlay().then(function() {
        if (overlayManager.active === 'printServiceOverlay') {
          overlayManager.close('printServiceOverlay');
        }
      });
      return; // eslint-disable-line no-unsafe-finally
    }
    let activeServiceOnEntry = activeService;
    activeService.renderPages().then(function() {
      return activeServiceOnEntry.performPrint();
    }).catch(function() {
      // Ignore any error messages.
    }).then(function() {
      // aborts acts on the "active" print request, so we need to check
      // whether the print request (activeServiceOnEntry) is still active.
      // Without the check, an unrelated print request (created after aborting
      // this print request while the pages were being generated) would be
      // aborted.
      if (activeServiceOnEntry.active) {
        abort();
      }
    });
  }
};

function dispatchEvent(eventType) {
  let event = document.createEvent('CustomEvent');
  event.initCustomEvent(eventType, false, false, 'custom');
  window.dispatchEvent(event);
}

function abort() {
  if (activeService) {
    activeService.destroy();
    dispatchEvent('afterprint');
  }
}

@Ugoku e @jtraulle Por favor, vote em https://bugzilla.mozilla.org/show_bug.cgi?id=911444 para colocá-lo no radar dos desenvolvedores do Firefox.

Obrigado @dotnetCarpenter , votei no Bugzilla 🐞

Tive o mesmo problema ao usar o firefox. Resolvido incluindo o pdf em um iframe como este (a chave é a forma como o pdf está vinculado):

`$ (". div_class "). html ('