Dompter Viadeo avec un Userscript

Comme je suis très curieux, il m’arrive souvent de m’intéresser aux parcours de vie des personnes que je rencontre online ou offline et fatalement, je tombe sur leur profil Viadeo. J’ai un compte Viadeo mais je ne suis pas systématiquement logué, d’autant que lorsqu’on est logué on laisse des traces : Viadeo enregistre toutes les visites pour permettre aux utilisateurs Premium de savoir qui a consulté leur profil.

Lorsque l’on arrive via Google sur un profil Viadeo sans être logué, au moindre mouvement sur la page s’affiche une fenêtre modale qui incite à s’inscrire :

La fenêtre modale incitant à s'inscrire

C’est un procédé marketing tout à fait légitime pour élargir le réseau mais c’est un peu agaçant pour le stalker que je suis. J’ai donc décidé d’y remédier par un Userscript.

Comme je l’expliquais ici, un Userscript est un petit morceau de Javascript qui va vous permettre de modifier le comportement d’un site selon vos souhaits.

Analyse de la page

Pour commencer on va aller inspecter le code de la page pour comprendre ce qui se passe. Affichage > Afficher la source ou Ctrl+u pour les pros.

On remarque en fin de page les instructions suivantes :

document.onmousemove = function(e) {
    if ( !moveDone ) {
        moveDone = true;
        createJoin();
        posFrame()
        posDiv();
        moveDiv();
    }
}

Une fonction anonyme va être appelée à chaque mouvement de la souris. C’est cette fonction qui alimente et affiche la fenêtre modale que l’on souhaite voir disparaître.

Un peu plus haut dans la source on trouve le div qui correspond à la fenêtre modale proprement dite :

<div style="position:absolute;display:none;text-align:right;padding-right:7px;" id="join">

Lorsque l’on bouge la souris, une Iframe contenant la page d’inscription est créée et injectée dans ce div, qui est alors affiché avec un joli effet de fading rendu possible par la bibliothèque Prototype.

Élaboration d’une stratégie

D’emblée, la solution qui paraît la plus élégante consiste tout simplement à “détacher” le gestionnaire d’évènement onMouseMove :

document.onmousemove = null;

Le problème c’est qu’une fois mise en pratique, cette solution ne suffit pas sous Chrome. Si l’on attend bien sagement que la page se charge complètement sans bouger la souris, alors ça fonctionne. Mais si pendant que la page se charge on bouge la souris, alors la fenêtre modale s’affichera. Il semble que le Userscript n’ait pas été exécuté assez tôt.

En y regardant de plus près avec les Outils de développement intégrés à Chrome (Ctrl + Shift + i), en particulier l’onglet Timeline qui affiche la chronologie de toutes les actions du navigateur, on remarque que l’évènement mousemove arrive bien avant l’exécution du Userscript.

Décomposons les étapes de travail du navigateur :

  • Chargement du code source par le navigateur ;
  • Parsing du code pour créer l’arbre DOM : évènement DOMContentLoaded ;
  • Chargement des ressources annexes (images, frames) ;
  • Page chargée : évènement Load.

(pour en savoir plus, voir la page How browsers work)

Sous Firefox, le Userscript est exécuté par Greasemonkey juste après l’évenement DOMContentLoaded. Sous Chrome, c’est aussi le cas par défaut. D’après la doc officielle, Il est possible de modifier ce comportement avec l’en-tête @run-at, notamment :

  • @run-at document-start : exécute le Userscript avant la création du DOM

Mais avec certaines versions de Chrome, cet entête est ignoré.

Bref, il va falloir trouver une autre ruse ! On va la jouer moins fine en supprimant carrément le div de la fenêtre modale, comme ça même si elle s’affiche quelques ms à cause d’un mouvement de la souris, elle disparaîtra aussitôt.

Pour cela, on va profiter des fonctions Prototype qui sont chargées avec la page :

$('join').remove();

Il reste un dernière obstacle : l’accès aux fonctions Javascript d’un site n’est normalement pas possible dans un Userscript, pour des raisons de sécurité. Pour contourner cette restriction, on peut utiliser la variable unsafeWindow sous Firefox. Mais pas sous Chrome. Pour assurer la compatibilité, deux solutions s’offrent à nous :

  • injecter un nouveau script dans la page avec notre code (exemples ) ;
  • utiliser le Location Hack

La deuxième solution est la plus facile :

location.assign("javascript:$('join').remove();void(0)");

En fait, ça revient à taper javascript:$('join').remove();void(0) dans la barre d’adresse.

Conclusion

En informatique, les choses les plus simples prennent souvent plus de temps que prévu ! Mais on a fini par y arriver :)

Le script final (une ligne !) se trouve là : http://userscripts.org/scripts/show/108665

Annexes

Il existe une extension pour Chrome qui reprend l’API de Greasemonkey et assure une compatibilité immédiate pour les milliers de scripts déja écrits : c’est Tampermonkey, dont voici la features list :

- full unsafeWindow access
- iframe support
- all GM_* functions including:
  * GM_registerMenuCommand
  * GM_xmlhttpRequest with cross domain support
  * GM_getResourceText
  * GM_getResourceURL
- the tags:
  * @resource and
  * @require

Du coté de Firefox, il existe un fork de Greasemonkey qui se veut plus dynamique : Scriptish. Il implémente notamment beaucoup plus de fonctionnalités.

Voici finalement quelques conseils pour faciliter les choses quand on code des Userscripts :

  • Installer l’extension Firebug pour Firefox / Firebug Lite pour Chrome pour tester des bouts de codes sur la page en live ;
  • Créer un Makefile pour mettre-à-jour le Userscript sans avoir à le réinstaller (voire même faire des liens symboliques pour travailler directement dessus), par exemple :
cp:
    cp viadeo.user.js ~/.mozilla/firefox/VOTRE_PROFILE.default/gm_scripts/viadeo_fix/viadeo_fix.users.js
    cp viadeo.user.js ~/.config/google-chrome/Default/Extensions/IDENTIFIANT/1.0.0/script.js
  • Pour que Chrome prenne en compte la nouvelle version, aller à chrome://extensions et Désactiver / Activer l’extension. La réinstaller si les headers ont été modifiés.