Pdf.js: Error: Permission denied to access property 'print'

Created on 23 Nov 2018  ·  39Comments  ·  Source: mozilla/pdf.js

Configuration:

  • Web browser and its version: all versions of Firefox since PDF.js was included (5+ years)
  • Operating system and its version: all
  • PDF.js version: all
  • Is a browser extension: n/a

Steps to reproduce the problem:

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

What is the expected behaviour?
That the PDF can print as in every other browser than Firefox

What went wrong?
Error: Permission denied to access property 'print'

Please fix this as the go to universal print solution of PDF in browser has been broken for 5 years in Firefox since pdf.js was included in Firefox.

The web developer community has hundreds of bad solutions to this, because of a single project, pdf.js.

4-printing

Most helpful comment

@dotnetCarpenter the icing on the cake is that, over a year ago, one of the developers complained that all of the +1 comments make it harder to see the technical discussion and therefore harder to resolve the bug. As if that's why it's been open for over 6 years and counting. Without the voting system, such comments are now the ONLY way to call attention to an issue, so I see no alternative.

All 39 comments

Similar to https://github.com/mozilla/pdf.js/issues/5397, but it does not matter if you use an iframe or not.

Same issue if using <object>

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

Steps to reproduce the problem:

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

Why open a duplicate issue here, when this is clearly already tracked in Bugzilla!?
Especially since this isn't even a bug in the (general) PDF.js library itself, but rather a limitation in the Firefox browser (as outlined in the linked bug, and a fix would thus not happen in this repository anyway).

@Snuffleupagus Because the Firefox bug was reported 5 years ago and the root cause is pdf.js and not Firefox. No Firefox developer has touch this and I have bump into this issue multiple times and it can only be solved by changing pdf.js not Firefox.

To clarify, the way pdf.js works is that the normal (15+ years) of printing a document, print(), in this case a PDF, is throwing an error when pdf.js is used, which is the default way of showing a PDF in Firefox for the past 5 years.

I might be wrong that the error is really how pdf.js is embedded into Firefox. But I assume that pdf.js could more easily listen for print() and use its internal logic to print the PDF document.

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');   
};

Should work since Firefox 6

window.matchMedia('print') will probably not work since bug https://bugzilla.mozilla.org/show_bug.cgi?id=774398 is not marked as fixed or resolved.

This is a duplicate of #5397 -- the root cause of the problem is that pdf.js is embedded into a document with a "resource://pdf.js" security principal. It's different from the embedding principal, so the same-origin policy blocks access to print and other properties. It doesn't matter if it's embedded in an iframe or an object.

@Snuffleupagus is the web folder part of the pdf.js bundle that's embedded in Firefox?
The only printing logic I have found is in https://github.com/mozilla/pdf.js/blob/master/web/firefox_print_service.js

The main issue with #5397 is that it's half about printing when using pdf.js and half about how to print a document in Firefox when pdf.js is rendering the document, as in this ticket. @automatedbugreportingfacility you're right but I felt this requires a fresh issue since #5397 is mudding the waters.

Changing the URI should happen in https://bugzilla.mozilla.org/show_bug.cgi?id=911444#c53 but in lieu of a fix in Firefox (haven't happen in 5 years), a work around would be to listen for the beforeprint event and start printing via pdf.js. If the beforeprint is blocked by Firefox, due to same-origin security policy, then it can only happen in Firefox.
Perhaps one of you can clarify the matter?

a work around would be to listen for the beforeprint event and start printing via pdf.js.

Can you clarify? For the beforeprint event to be sent to an embedded pdf.js document, you need to invoke print() in the context of a parent window. The browser will then print the contents of the parent window. You can't "start printing" in the event handler, because it had already started printing the parent document.

A potential workaround on the pdf.js side would be to implement an onmessage handler to allow printing through pdfWindow.postMessage("print");, but I'm not sure if it's a desired solution.

A potential workaround on the pdf.js side would be to implement an onmessage handler to allow printing through pdfWindow.postMessage("print");, but I'm not sure if it's a desired solution.

@automatedbugreportingfacility uf, no that is not desirable at all. The perfect solution would be to have DOM API parity with all other browsers, where you can use .print() on the PDF document container.

I didn't create this issue because I use pdf.js but because Firefox uses pdf.js and print() hasn't worked since pdf.js became the standard for rendering PDF's in Firefox.

I will be happy if this gets fixed in Firefox and not pdf.js or the other way around - either way I'll be happy 😃

[...] then it can only happen in Firefox.
Perhaps one of you can clarify the matter?

I already state in https://github.com/mozilla/pdf.js/issues/10290#issuecomment-441132851 that it's not relevant to this repository, and https://github.com/mozilla/pdf.js/issues/10290#issuecomment-441202543 outlines (in some detail) why that is. Again, please note that it's not necessary/desirable to have duplicate issues open.

In order to even touch .print without a security error being thrown, a fix is needed for the resource://pdf.js situation I described above, and this would be done in Firefox. We can close this issue since there's no pdf.js work to do here, and the upstream bug is mirrored in #5397.

@Snuffleupagus and @automatedbugreportingfacility just to be sure I understand what you are saying.

There is no way to create a work-around Firefox security policy in pdf.js, when print() is called. Hence print() will always throw in Firefox because of how pdf.js is embedded in Firefox.

Is the above correct?

Yes, you can't punch a hole in the browser's security mechanisms. Embedding pdf.js in a semi-privileged document was a big mistake in the first place, but there's no going back, and Mozilla sadly prefers spending money on ephemeral things like "Project Mortar". But I digress.

The Mortar experiment has concluded. Mozilla does not consider the PDF use case justifies the burden of implementing and maintaining PDFium and a Pepper API implementation in Gecko.

Well at least Motar is discontinued.

This issue could definitely be closed but before I (you) do, since I got 2 pdf.js experts here, I have two questions that possibly could help https://bugzilla.mozilla.org/show_bug.cgi?id=911444 along in the right direction.

  1. How should pdf.js be embedded in Firefox, if not as a special document (_resource:// protocol_)?
  2. What is the paper print layout when Firefox prints pdf.js, toolbars etc?

Embedding pdf.js in a semi-privileged document was a big mistake in the first place, but there's no going back

@automatedbugreportingfacility Why is this decision irreversible?

Couldn't you just create a new blank document with pdf.js and the same origin as the parent window and feed the PDF file to pdf.js?

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

Bonus points, if pdf.js listen for beforeprint, cancel the event and print the <canvas> (PDF document) and not letting FIrefox print the pdf.js UI.

I imagine, if pdf.js was embedded as a regular document, you would able to listen to the parent window.

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

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

Or change pdf.js to:

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

On second thought, this would mean that pdf.js would swallow prints from the parent which is not what we want.

Actually pdf.js is already doing the right thing. We just need firefox to dispatch print() on the document that embeds pdf.js.

Excerpt from _pdf_print_service.js_ (found on 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 and @jtraulle Please vote on https://bugzilla.mozilla.org/show_bug.cgi?id=911444 to get it on the radar for Firefox developers.

Thanks @dotnetCarpenter, I have voted on Bugzilla 🐞

Had the same issue using firefox. Solved it including the pdf into an iframe like this (the key is the way the pdf is linked):

`$(".div_class").html('');
$('#frame_id')
.attr("src", "path_to/PDFJS/web/viewer.html?file=path_to/file.pdf")
.on("load", function(){
setTimeout(printWhenReady, 3000);
});
}

function printWhenReady(){
document.getElementById(frame_id).contentWindow.print();
}`

Why was this re-opened, when it's been stated repeatedly that it's a duplicate of https://bugzilla.mozilla.org/show_bug.cgi?id=911444 and not something that can be fixed in this repository!?

@timvandermeij Can you please close this issue?

I reopened it so that it is visible to the thousands of web developers that
eventually run into this issue. It makes it easy to spot and guide people
to the bugzilla issue. I thought it was better than keep getting duplicates
but I regress.

On Tue, Jan 8, 2019 at 11:21 PM Tim van der Meij notifications@github.com
wrote:

Closed #10290 https://github.com/mozilla/pdf.js/issues/10290.


You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
https://github.com/mozilla/pdf.js/issues/10290#event-2061484528, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AACq8wR4vNFtCtaUI-VRshKnQyDCQoZVks5vBRoGgaJpZM4Yv9So
.

Had the same issue using firefox. Solved it including the pdf into an iframe like this (the key is the way the pdf is linked):

`$(".div_class").html('');
$('#frame_id')
.attr("src", "path_to/PDFJS/web/viewer.html?file=path_to/file.pdf")
.on("load", function(){
setTimeout(printWhenReady, 3000);
});
}

function printWhenReady(){
document.getElementById(frame_id).contentWindow.print();
}`

no, still SecurityError: Permission denied to access property "print" on cross-origin object error in firefox console

Had the same issue using firefox. Solved it including the pdf into an iframe like this (the key is the way the pdf is linked):
$(".div_class").html('<iframe id="frame_id"></iframe>'); $('#frame_id') .attr("src", "path_to/PDFJS/web/viewer.html?file=path_to/file.pdf") .on("load", function(){ setTimeout(printWhenReady, 3000); }); } function printWhenReady(){ document.getElementById(frame_id).contentWindow.print(); }

no, still SecurityError: Permission denied to access property "print" on cross-origin object error in firefox console

@shmilyoo Please how did you get the path to PDFjs ??

The problem is the viewer. The embedded viewer causes the cross-origin problem. Try creating your own viewer. That will solve the problem. e.g. from here: https://pspdfkit.com/blog/2019/implement-pdf-viewer-pdf-js/

Or if you need a full featured viewer, you can use the Mozilla one from here: http://mozilla.github.io/pdf.js/web/viewer.html (for this one you will need to download the latest pdf.js and pdf.worker.js implementation). I just did that for a project at work, and it works like a charm.

@vaspervnp If I may ask, were you able to programmatically call the print function ?

@vaspervnp The irony is that, that is the exact same Mozilla viewer embedded in Firefox!

We really need someone to change how pdf.js is embedded in Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=911444#c58

@vaspervnp If I may ask, were you able to programmatically call the print function ?

Yes, I was.

@vaspervnp it will be nice if you could provide a little code snippet on how you did that.

@didagu
I didn't write any code additional. I just included the javascript and the viewer from here: http://mozilla.github.io/pdf.js/web/viewer.html Then, when using the viewer the way the embeded one is used, it just worked.

Do you need special privileges to vote on bugzilla? I don't see that option anywhere.

@mdodge-ecgrow looks like bugzilla removed the voting feature when they made the re-design. I'm not sure how we´re suppose to get firefox developers attention now...

@dotnetCarpenter the icing on the cake is that, over a year ago, one of the developers complained that all of the +1 comments make it harder to see the technical discussion and therefore harder to resolve the bug. As if that's why it's been open for over 6 years and counting. Without the voting system, such comments are now the ONLY way to call attention to an issue, so I see no alternative.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

timvandermeij picture timvandermeij  ·  28Comments

AliND picture AliND  ·  29Comments

agilgur5 picture agilgur5  ·  32Comments

ousia picture ousia  ·  29Comments

StevenHarlow picture StevenHarlow  ·  29Comments