Re: Review of 3.14.11. The canvas element

Hello Philip!

Le Tue, 21 Aug 2007 20:41:17 +0300, Philip Taylor  
<philip@zaynar.demon.co.uk> a écrit:

> Mihai Sucan wrote:
>> 3. The getContext() method should be defined such that any number of  
>> additional arguments are allowed, just like toDataURL() is defined.  
>> This is forward thinking about initializing various contexts with any  
>> settings.
>
> I believe that is already covered by "1.3.1. Common conformance  
> requirements for APIs exposed to JavaScript": "Unless other[wise]  
> specified, if a method is passed more arguments than is defined for that  
> method in its IDL definition, the excess arguments must be ignored."

The specification explicitly states the following about toDataURL():

"Arguments other than the type must be ignored, and must not cause the  
user agent to raise an exception (as would normally occur if a method was  
called with the wrong number of arguments). A future version of this  
specification will probably allow extra parameters to be passed to  
toDataURL() to allow authors to more carefully control compression  
settings, image metadata, etc."

Thus I assumed that under normal circumstances, calling a method with  
wrong arguments raises an exception.

Therefore, I suggest saying the same about getContext(), or remove the  
above paragraph from the definition of toDataURL(). The latter seems more  
appropriate, given the common conformance requirements for APIs.


>> 5. Drawing states should be saveable with IDs, and for easier restoring.
>>  save(id)
>> restore(id)
>>  If id is not provided, then save() works as defined now. The same for  
>> restore().
>>  Currently, it's not trivial to save and restore a specific state.
>
> I think a more convenient syntax would be:
>    var state = ctx.save();
>    ctx.restore(state);
> But how would it interact with normal calls to ctx.restore()?

The syntax you've suggested is interesting as well.

When a state is saved with an ID, it's not pushed into the states stack,  
and cannot be restored unless you explicitly use restore(id).


> I'm unsure what are the cases where you'd want to do non-stack-based  
> save/restore and would use restore(id) rather than simply defining and  
> calling your own function to set the whole state each time.

It's not only about the "use case". They are all the same.

It's just the "programming style" (if I can call it like this). I would  
personally favor using my own ids for states.


>> I don't believe it can be argued that such changes break (too many)  
>> applications. Today's applications using canvas are experiments. The  
>> entire spec is subject to change, and as such nobody should complain.
>
> They're not all experiments - I found  
> http://www.city-data.com/city/Hardy-Iowa.html (using PlotKit on canvas)  
> via  
> <http://canvex.lazyilluminati.com/survey/2007-07-17/analyse.cgi/tag/canvas>.  
> Apparently there's Yahoo Pipes too. I've no idea how many other  
> non-experiments there are, though.

Hmm.. thay *are* experiments.

Yahoo Pipes is an experiment.


>> 7. On the basis of save()/restore() state, I think it would be a good  
>> idea (performance-wise, for various applications), to be able to do  
>> something like this:
>>  saveImage(id)
>> restoreImage(id)
>
> That effect should already be possible, like:
>
> CanvasRenderingContext2D.saveImage = function(x, y, w, h) {
>   var canvas = document.createElement('canvas');
>   canvas.width = w;
>   canvas.height = h;
>   canvas.getContext('2d').drawImage(this.canvas, x, y, w, h, 0, 0, w, h);
>   return canvas;
> };
> CanvasRenderingContext2D.restoreImage = function(canvas, x, y) {
>   this.drawImage(canvas, x, y);
> };
>
> (untested), which should be sufficiently fast and memory-efficient.

Yes, that would be better than using a data URI, or an ImageData object.  
However, it's still not as efficient as a native implementation, simply  
because you actually create a new canvas for saving the image into memory.  
That's too much. The UA can only store the image into the memory, it  
wouldn't create a whole canvas, with all the properties and methods, etc.  
etc.


>> 9. I would propose something different, a different idea. Why not  
>> define an optional method for the 2d context, which allows authors to  
>> say something like importNodeRender()? Here's the "funky" idea:
>>  importNodeRender(node)
>>  ... where node is any DOM node, e.g.  
>> document.getElementById('whatever'). The way "captures" the rendered  
>> image of that element, irrespective what it is (maybe it's SVG, Flash,  
>> simple HTML+CSS, whatever).
>>  importDocument(x, y, w, h)
>>  This method could allow the author to capture a part of the rendered  
>> document page. x and y positions are taken from the entire document,  
>> not just the visible page, in the current window size.
>> [...]
>> Would this be overly complex? Popular UAs already have ways to generate  
>> page thumbs.
>
> Mozilla has a non-standard drawWindow method, to draw whole Windows into  
> the canvas (e.g. for thumbnails), which sounds similar to your proposal.  
> It is limited to trusted content (like extensions) for security reasons:
>
>    // We can't allow web apps to call this until we fix at least the
>    // following potential security issues:
>    // -- rendering cross-domain IFRAMEs and then extracting the results
>    // -- rendering the user's theme and then extracting the results
>    // -- rendering native anonymous content (e.g., file input paths;
>    // scrollbars should be allowed)
> <http://lxr.mozilla.org/mozilla/source/content/canvas/src/nsCanvasRenderingContext2D.cpp#2305>
>
> as well as issues like rendering cross-domain <img>s or rendering  
> <canvas>s that have had cross-domain Images drawn onto them, etc. (I  
> don't know if this means it's overly complex or infeasible-to-secure, or  
> not.)
>

If the script is on the same (sub)domain as the page, then allow using  
drawWindow(), if not raise an exception.

The idea is: the page includes the script, it's therefore trusted, being  
hosted in the same place. If the page includes cross-domain  
IFRAMEs/images/objects/embeds, then hide them in the render.

However, take into consideration two facts:

1. the JavaScript function doesn't need to capture the page render to  
steal the information from inputs. That's obvious - the script can use the  
DOM to take the vlues directly. You can't protect anyone from that. Thus,  
I see no reason to consider this a security issue, more than, say, having  
scripts themselves running in the page...

2. the drawImage() method defined by the HTML 5 spec can take an  
HTMLImageElement. The spec does not define any security-related  
restrictions. One could go about drawWindow in the same way.

(or is this a "bug" in the spec? Maybe Hixie should address this issue.)



-- 
http://www.robodesign.ro

Received on Wednesday, 22 August 2007 10:07:08 UTC