Réaliser des copies d'écran depuis une application web
Par Clochix le vendredi 24 avril 2009, 02:59 - Technoweb - Lien permanent
Au départ, une discussion à la pause syndicale sur le meilleur moyen de réaliser les copies d'écrans que tout service de partage de marque-pages permet à présent d'associer à un lien. Et l'envie de faire un peu de réclame pour Firefox. Au final, une solution permettant de créer une copie d'écran en quelques lignes de JavaScript directement dans Firefox. Mais ni très élégante, ni réellement utilisable. Je la couche ici en 2 mots pour me souvenir de la méthode.
Canvas, kesako ?
Canvas est une balise HTML offrant une ardoise où dessiner. Créée par Apple pour Safari, la balise est en phase d'incorporation à HTML 5, et a été intégrée depuis longtemps à Firefox et Opera. Cette balise dispose d'une API avec des fonctions de dessin en deux dimensions. Bien qu'elle existe depuis longtemps, elle restait très peu utilisée, mais depuis quelques mois des annonces plus alléchantes les unes que les autres se succèdent. Par exemple, lorsque les Mozilla Labs ont lancé leur projet d'IDE en ligne, Bespin, ils ont choisi de se baser non sur une textarea enrichie mais sur Canvas pour développer l'éditeur de fichiers[1]. Il y a quelques semaines, Mozilla et Khronos ont annoncé la création d'un groupe de travail visant à proposer un standard ouvert pour faire de la 3D sur le Web. L'implémentation s'appuiera très probablement sur Canvas et JavaScript[2]. Les impressionnantes démonstrations mitonnées par Paul Rouget des nouvelles fonctionnalités de Firefox 3.5 utilisent elles aussi allègrement Canvas, et il ne se passe pas une semaine sans qu'Ajaxian ne cite de nouveaux projets utilisant cette technologie. Bref, si ce n'est déjà fait, vous devriez jeter un œil à la bête.
Canvas, copieur !
En 2005, Robert
O'Callahan a ajouté à Canvas dans Gecko une
nouvelle méthode, drawWindow qui permet de dessiner à l'intérieur
d'un canvas une partie de la fenêtre du navigateur. A ma connaissance, aucun
autre navigateur ne l'implémente. Sans doute à cause des nombreux risques
qu'elle peut faire courir à l'utilisateur. Un site web pourrait tout à fait
l'utiliser pour réaliser des copies d'écran des sites consultés par ses
visiteurs. Les risques de vol de données et d'atteintes à la vie privée sont
élevés. Pour cette raison, cette méthode n'est pas accessible dans le contexte
des pages web, mais uniquement appelable depuis le chrome (grosso-modo, les
extensions). Il existe cependant un moyen de contourner cette restriction, et
de faire appel à la fonction depuis un contenu web: en utilisant du
code signé.
Le cambouis, enfin
La procédure pour signer une application web est très bien décrite en détail sur XULfr, je ne vais pas la paraphraser. Il faut créer un certificat, empaqueter son application dans une archive jar, et la signer. Une application signée peut ensuite demander des droits supplémentaires.
Concrètement, pour utiliser le petit script ci-dessous, l'internaute devra charger dans son navigateur le certificat que vous avez utilisé pour signer l'application, puis, au moment de l'exécution de celle-ci, l'autoriser à gagner des droits. Le reste n'est que littérature, et si vous voulez tester, je vous propose ce petit bout de code:
<html>
<head>
<title>Screenshot</title>
<style type="text/css">
body{
background-color: #888;
}
</style>
</head>
<body>
<iframe id="frame" width="1024" height="768" style="overflow: hidden; display: none;"></iframe>
<form>
<input type="text" id="url" />
<input type="button" onclick="frame.src = document.getElementById('url').value" value="submit"/>
</form>
<img id="screenshot" style="display: none" />
<canvas id="canvas" width="1024" height="768" style="display: none"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var frame = document.getElementById('frame');
var img = document.getElementById('screenshot');
var ctx = canvas.getContext("2d");
frame.addEventListener("load", function(){
img.style.display = 'block';
frame.style.display = 'block';
ctx.scale(0.5, 0.5);
// Sans cette ligne qui demande à l'utilisateur d'accorder certains
// droits au script, l'appel à drawWindow renverra une erreur
netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
ctx.drawWindow(window,
frame.offsetLeft,
frame.offsetTop,
frame.offsetWidth,
frame.offsetHeight,
"rgb(0,0,0)");
ctx.scale(2, 2);
frame.style.display = 'none';
img.src = canvas.toDataURL();
img.style.display = 'block';
}, true);
</script>
</body>
</html>
Le code est simple: on ouvre le site distant dans une iframe masquée. Une
fois la page chargée, on affiche brièvement l'iframe le temps de faire une
copie d'écran avec drawWindow et on convertit l'image affichée
dans le Canvas avec toDataURL qui va créer une url de type
data:image/png;base64, contenant l'image encodée en Base64. J'affiche directement
l'image, mais la poster pour la stocker sur un serveur ne demanderait qu'un
appel Ajax.
Au final, on a là un moyen simple de réaliser par exemple une bookmarklet pour créer des marque-pages illustrés d'une copie du site. Mais avec 2 grosses restrictions:
- ça ne fonctionnera qu'avec Firefox;
- l'utilisateur doit vous faire suffisamment confiance pour accepter votre certificat et accorder les privilèges nécessaires à l'application;
- on me souffle également que cette méthode ne copie que ce qui est affiché par le navigateur lui-même, et non par des plug-ins. Les contenus flash ne devraient donc pas être visibles;
Bref, ça ne peut être qu'un petit cadeau aux utilisateurs de Firefox, pour les autres il faudra trouver une solution côté serveur pour réaliser les copies d'écran.
Vous trouverez en pièce jointe le fichier jar contenant cette page, et le certificat ayant servi à signer le fichier. Pour les utiliser, installez-les sur un serveur et:
- ajoutez si elles n'existent déjà les 2 lignes suivantes à la configuration d'Apache, afin qu'il envoie le bon type MIME lorsque vous demanderez les fichiers:
AddType application/x-x509-ca-cert .crt AddType application/java-archive jar
- appelez l'URL du certificat: Firefox devrait vous proposer de l'installer;
- appelez l'application en utilisant le sheme jar. Par exemple, si elle est
installée à la racine de votre serveur:
jar:http://localhost/screen.jar!/screen.html
Oualou. Questions, commentaires ?
Notes
[1] Ben Galbraith a longuement expliqué les raisons de ce choix sur son blog, ici et là
[2] et c'est au passage une très bonne nouvelle puisqu'avec la réalité augmentée dont j'ai déjà parlée, la 3D risque d'être une des principale technologies qui va enfin prendre son envol sur le Web. Or pour l'instant elle est essentiellement disponible via des technologies propriétaires comme Flash. Des tentatives sont en cours depuis longtemps pour faire de la 3D avec Canvas, si le sujet vous intéresse je vous conseille la lecture de cette introduction sur le site de Vladimir Vukićević. De son côté, Google vient d'annoncer O3D, également dans l'optique de développer un standard ouvert pour la 3D sur le web
Commentaires
« marques-pages » => marque-pages
Je n'ai bien sûr aucune objection à la suppression de ce commentaire.
Merci Mozinet, j'ai corrigé et je garde ton commentaire dans l'espoir qu'il m'aide à ne plus faire la faute à l'avenir.