RootsLabs

More than a tool ! GitHub Google+ LinkedIn RSS

Firefox OS : Dev Tips #7

Progi1984 - Commentaires (1)

Après un mois d’absence, me voici de retour avec de nouvelles astuces pour Firefox OS :

  • Quels sont les comptes Twitter à suivre ?
  • Comment faire de l’OAuth dans une application Firefox OS ?
  • WebAPI : WebActivities

Quels sont les comptes Twitter à suivre ?

Les évangélistes Firefox OS

Angelina Fabbro est une techno évangéliste pour Mozilla (Vidéo d’introduction). Elle écrit de nombreux articles sur Firefox OS sur MozHacks. Elle est spécialisée en JavaScript.

Frédéric Harper est un techno évangéliste pour Mozilla (Vidéo d’introduction).

Jason Weathersby est un techno évangéliste pour Mozilla (Vidéo d’introduction)

Autre techno évangéliste chez Mozilla, Robert Nyman écrit aussi des articles sur la blog de MozHacks avec une expertise en HTML5.

Les modérateurs Firefox OS

Adora a.k.a. Lisa Brewster est une « app reviewer » pour le Firefox Marketplace.

Les comptes d’informations Firefox OS

@FirefoxOSFeed est un fil Twitter regroupant les dernières infos sur Firefox OS. Il fait partie des must-have.

@AllFirefoxOS est un fil Twitter lié au site allfirefoxos.com.

@FirefoxApps est le compte Twitter officiel du Firefox Marketplace.

@TheFirefoxos est un fil Twitter lié au site thefirefoxos.com.

Comment faire de l’OAuth dans une application Firefox OS ?

Pour vous montrer comment faire de l’OAuth avec une application Firefox OS, je vais prendre l’exemple d’une application Facebook.

Créer une application Facebook

Pour cela, il faut aller sur le site Developers FB. A ce niveau là, vous créez une nouvelle application avec le nom souhaité. Quand celle ci est créé, vous n’avez plus rien à modifier. Vous n’avez à récupérer que son Application ID.

Firefox Os : OAuth avec une App Facebook

Créer l’application Firefox OS

Le fichier manifest.webapp

Tout d’abord, il faut un fichier manifest.webapp :

{
  "name": "FacebookAPI",
  "description": "FacebookAPI",
  "launch_path": "/index.html",
  "developer": {
    "name": "Progi1984",
    "url": "http://rootslabs.net"
  },
  "icons": {
      "128": "/img/default.png"
  },
  "permissions": {
    "systemXHR": { "description":"Used to send data to Facebook API." },
    "browser": { "description":"Enables authentication to Facebook via OAuth." }
  },
  "type":"privileged"
}

On lui donne accès à deux permissions pour qu’il puisse lancer l’authentification vers Facebook dans un navigateur, et lancer des requêtes AJAX vers Facebook.

Le fichier index.html

Puis on lui associe un fichier index.html qui sera le coeur de notre application.

<html>
  <body>
    <input id="btnLogin" value="Login" type="button" />
    <input id="btnLogout" value="Logout" type="button" />
    <iframe mozbrowser remote id='browser' style="width:100%;height:100%;overflow:true;"></iframe>
    <script>
      var gAccessToken = 0;
      /**
        * Utility function to parse OAuth authorization token out of a URL.
        */
      function parseTokens(psUrl) {
        if(psUrl.lastIndexOf('?') == -1){
          var psUrl = psUrl.slice(psUrl.lastIndexOf('#') + 1);
        } else {
          var psUrl = psUrl.slice(psUrl.lastIndexOf('?') + 1);
        }        
        var result = {};
        psUrl.split('&').forEach(function(parts) {
            parts = parts.split('=');
            console.log(parts);
            result[parts[0]] = parts[1];
        });
        return result;
      } 
      // INIT
      document.getElementById('btnLogout').style.display = 'none';
      document.getElementById('browser').style.display = 'none';
      // LOGIN
      function fnClick_btnLogin(){
        console.log('fnClick_btnLogin');
        sURLRedirect = 'https://www.facebook.com/connect/login_success.html';
        sURLAuth = 'https://www.facebook.com/dialog/oauth' 
          + '?client_id=XXXXXXXXXXXXXX' /* Remplacer la série de X par l'Application ID */
          + '&redirect_uri=' + sURLRedirect
          + '&response_type=token'
          + '&scope=email';
          + '&display=touch';
        document.getElementById('browser').addEventListener('mozbrowserlocationchange', function(e) {
          if (e.detail && (e.detail.indexOf(sURLRedirect) === 0)) {
            var result = parseTokens(e.detail);
            var tokens = JSON.stringify(result);
            console.log('Facebook Access Token : ' + result['access_token']);
            gAccessToken = result['access_token'];
            document.getElementById('browser').style.display = 'none';
            document.getElementById('btnLogout').style.display = 'block';
          }
        });
        document.getElementById('browser').setAttribute('src', sURLAuth);
        document.getElementById('browser').style.display = 'block';
        document.getElementById('btnLogin').style.display = 'none';
      }
      document.getElementById('btnLogin').addEventListener('click', fnClick_btnLogin, false);
      // LOGOUT
      function fnClick_btnLogout(){
        console.log('fnClick_btnLogout');
        console.log(gAccessToken);
        sURLRedirect = 'https://www.facebook.com/connect/login_success.html';
        document.getElementById('browser').addEventListener('mozbrowserlocationchange', function(e) {
          if (e.detail && (e.detail.indexOf(sURLRedirect) === 0)) {
            var result = parseTokens(e.detail);
            var tokens = JSON.stringify(result);
            console.log('Facebook Access Token : ' + result['access_token']);
            document.getElementById('browser').style.display = 'none';
            document.getElementById('btnLogin').style.display = 'block';
          }
        });
        document.getElementById('browser').setAttribute('src', 'https://www.facebook.com/logout.php?next='+sURLRedirect+'&access_token=' + gAccessToken);
        document.getElementById('browser').style.display = 'block';
        document.getElementById('btnLogout').style.display = 'none';
      }
      document.getElementById('btnLogout').addEventListener('click', fnClick_btnLogout, false);
    </script>
  </body>
</html>

Notre page web est composé de deux boutons : Login & Logout et d’une iframe.

Par défaut, je cache le bouton Logout et l’iframe.
Quand je clique sur le bouton Login, j’affiche l’iframe et lui définit comme adresse une URL d’authentification qui, après authentification de l’utilisateur, me retournera dans la nouvelle URL un paramètre access_token utilisé pour mes différents appels API.
Pour récupérer cette nouvelle URL, j’ajoute un listener ‘mozbrowserlocationchange’ à l’iframe. Celui-ci interceptera tous les changements d’URL pour cet élément HTML.

La technique utilisée pour faire de l’OAuth dans une application Firefox OS est identique à celle utilisée pour les applications de type Desktop ayant un accès au Web mais pas d’URL publique.
Cette technique est utilisée par la plupart des fournisseurs d’authentification OAuth :

WebAPI : WebActivities

Les WebActivities permettent de lier les différentes applications ensemble. Ainsi, l’application Twitter va offrir une WebActivity Share pour partager sur Twitter ou l’application Contacts va offrir une WebActivity Webcontacts/Contact pour créer rapidement un contact.

Lier son application à une WebActivity

Il faut d’abord définir dans le fichier manifest.webapp les WebActivities que fournira votre application.
Dans l’exemple ci-dessous, on voit que l’application permettra de visualiser les images de type GIF ou PNG et que ce sera le fichier image_view.html de l’application qui gérera.

"activities": {
  "view": {
    "filters": {
      type: ["image/png", "image/gif"],
    },
    "href": "image_view.html",
    "disposition": "window"
  }
}

Dans le fichier HTML, on a d’abord l’enregistrement du fournisseur de WebActivity :

var oActivityHandler = navigator.mozRegisterActivityHandler({
    name: "view", 
    disposition: "inline", 
    filters: {
        type: ["image/png", "image/gif"]
    }

});
 
oActivityHandler.onerror = function () {
    console.log('Echec de l\'enregistrement du fournisseur de WebActivity view');

}

Ensuite, on gère la WebActivity :

navigator.mozSetMessageHandler("activity", function (a) {

    var img = getImageObject();

    img.src = a.source.url;

    // Appelle a.postResult() ou a.postError() si la WebActivity doit retourner une valeur
});

Et voilà, votre application est désormais capable de gérer la visualisation d’images pour l’ensemble des applications de votre téléphone.

Utiliser une WebActivity dans son application

De nombreuses WebActivities sont fournies par défaut. En voici quelques unes :

Appeler quelqu’un :

var oMozActivity = new MozActivity({
    name: "dial",
    data: {
        number: "+33600000000"
    }
});

Envoyer un SMS :

var oMozActivity = new MozActivity({
    name: "new",
    data: {
        type: "websms/sms",
        number: "+33600000000"
    }
});

Enregistrer un contact :

var oMozActivity = new MozActivity({
    name: "new",
    data: {
        type: "webcontacts/contact",
        params: {
            giveName: "givenName",
            familyName: "FamilyName",
            tel: "+33600000000",
            email: "email@fai.tld",
            address: "Adress",
            note: "Note",
            company: "Company"
        }
    }
});

Visualiser une URL :

var oMozActivity = new MozActivity({
    name: "view",
    data: {
        type: "url",
        url: "http://url.tld"
    }
});

Enregistrer un favori :

var oMozActivity = new MozActivity({
    name: "save-bookmark",
    data: {
        type: "url",
        url: "http://url.tld",
        name: "Bookmark Name",
        icon: "http://url.tld/favicon.png"
    
}
});

Choisir une image :

var oMozActivity = new MozActivity({
   name: "pick",
   data: {
       type: ["image/png", "image/jpg", "image/jpeg"]
   
}
});

D’autres WebActivities sont disponibles :

  • configure
  • costcontrol/balance
  • costcontrol/data_usage
  • costcontrol/telephony
  • open
  • record
  • share
  • test

Il faut savoir ensuite gérer le retour de cette WebActivity (est ce qu’il a bien retourné ce que je voulais ? est ce qu’il y a eu une erreur ?).
Nous allons prendre le cas de la WebActivity ‘pick’ :

oMozActivity.onsuccess = function () {

    // Créee une image et définit le blob retourné comme source de l'image
    var img = document.createElement("img");
    img.src = window.URL.createObjectURL(this.result.blob);
 
    // Affiche l'image dans votre application
    var imagePresenter = document.querySelector("#image-presenter");
    imagePresenter.appendChild(img);
};
 
oMozActivity.onerror = function () {

    // Si une erreur est apparu ou que l'utilisateur a annulé l'opération
    alert('Erreur avec la MozActivity pick');
};

Liens :

Commentaires

1. RootsLabs » Firefox OS : Dev Tips #8, le 17 septembre 2013 à 10:30

[…] l’épisode 7 des Dev Tips Firefox OS, quels sont les nouveautés […]

Ajouter un commentaire

Commentaire :