canvas.toDataURL('image/png') throwing SecurityError for video from remote PeerConnection in Firefox Beta (32)




WebRTC: Audio/Video
4 years ago
3 years ago


(Reporter: Adam Ullman, Unassigned)



32 Branch
Mac OS X

Firefox Tracking Flags

(firefox31 unaffected, firefox32 affected, firefox33 unaffected, firefox34 unaffected, b2g-v2.0 ?)



(1 attachment)



4 years ago
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:32.0) Gecko/20100101 Firefox/32.0 (Beta/Release)
Build ID: 20140825202822

Steps to reproduce:

1. Open the following URL in 2 browser windows, Firefox Beta (32).
2. You will be asked to allow access to your camera and microphone in both windows. Allow access.
3. You will see yourself twice in each window in 2 video elements. Then it will start an interval that takes a screenshot of the remote video window every 1000 milliseconds and put it on the screen. This is using:

      var canvas = OT.$.createElement('canvas', {
        width: _domElement.videoWidth,
        height: _domElement.videoHeight,
        style: { display: 'none' }

      try {
        canvas.getContext('2d').drawImage(_domElement, 0, 0, canvas.width, canvas.height);
      } catch(err) {
        OT.warn('Cannot get image data yet');
        return null;
      var imgData = canvas.toDataURL('image/png');

Actual results:

In Firefox Beta (32) you get the following error in the console every time it tries to do toDataURL;

"SecurityError: The operation is insecure."

Expected results:

An image of the remote video should be generated every second and placed on the page. This works in Firefox stable and Aurora. It also works in Chrome.
Confirmed on 29 (since I had it), latest beta (fails), aurora and nightly; all work but beta.

Possible regression from the identity work; perhaps a patch that didn't uplift?

I'll note that the "snapshot" feature (of a local stream) on gum_test.html works, which would also point at identity.

Note that it's too late for 32 release; if we get a safe fix fast it might be possible to include in any possible 32.1 release.
status-b2g-v2.0: --- → ?
status-firefox31: --- → unaffected
status-firefox32: --- → affected
status-firefox33: --- → unaffected
status-firefox34: --- → unaffected
Ever confirmed: true
Flags: needinfo?(martin.thomson)
Keywords: regression
Created attachment 8481454 [details] [diff] [review]

I modified an existing test case for this (see attached).  It passes.  But there's a trick.

There is a period over which new remote media is assigned the null principal, which makes it inaccessible to content (which causes the security error).  But that period exists only prior to the DTLS connection being established, when we don't know if the remote peer has isolated streams or not.

During that period, you will have a dead video stream, it's probably rendered as black frames.  That stream is inaccessible to content until we know that it's safe to make it accessible.  This is particularly noticable on the answerer side of RTCPeerConnection because streams (should) appear immediately after setRemoteDescription, where you are guaranteed not to receive content from your peer.

The trick here is that if you render inaccessible content to a canvas, it renders, but taints the canvas.  A tainted canvas can't be sampled from.  This is a state from which a canvas cannot return.  If you have rendered inaccessible content at any point in the history of the canvas, the canvas will always return a security error when you attempt to sample from it.

The workaround for this is to create a new canvas for every attempt to sample the image, like my test does.  Once you are able to successfully sample from the video, you should be fine to reuse the canvas.

You might reasonably argue that there is a bug in the specification here such that this can occur.  But I'm not smart enough to work out a solution that doesn't also require major structural changes to RTP or RTCPeerConnection.
Flags: needinfo?(martin.thomson)

Comment 3

4 years ago
I am generating a new Canvas each time in the jsbin sample above. It's still giving this error and never recovering, even when there is video. In fact if you inspect the DOM you can see the Canvas elements continually getting inserted and not cleaned up (because of the error).

I may be missing something here though. Is there a workaround? Do I just need to wait longer before requesting the image? I tried waiting 10 seconds instead of 1 second and I'm getting the same result:
See comment 3
Flags: needinfo?(martin.thomson)
One thing that I note is that you need to guard the following:

      var imgData = canvas.toDataURL('image/png');

With a try/catch block to catch the security error.  But that's not going to be the problem.

I'll get 32 and see what happens; I'm getting no gUM prompt on Nightly.

Certainly, I can't imagine this taking any more time than it takes to establish the DTLS session, which is not going to be more than 5 seconds.  More commonly it will be <1s.


4 years ago
Duplicate of this bug: 1072219
I've tested this on 33 and the issue is not there.  Since this is specific to 32, and this alone isn't worth respinning for, I'd conclude that we'll just wait for 33 to come around.
Flags: needinfo?(martin.thomson)

Comment 8

4 years ago
I confirm the WebGL+WebRTC integration at works fine on Firefox 33.0b7 and not 32.0.3.
Last Resolved: 3 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.